8

Go的context解密

 3 years ago
source link: https://studygolang.com/articles/29287
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go中的context包在Go1.7的时候由google贡献引入Go SDK中。在并发的场景下基本都会用到context这个包的功能。 

什么是context?

中文翻译为“上下文”,具体应用在goroutine中。用作goroutine的控制手段。context 主要用来在各个goroutine之间传递上下文。包括:cancel,timeout等。(个人在开发中用作超时控制,类似:前端一个require但是后端比较繁忙。比如5s无法返给前端response。这样就直接返回timeout并且取消这个goroutine。)

随着context 包的引入,标准库的很多接口带上ctx 参数。类似 database/sql 。context基本就是成为控制并发控制&&超时控制的标准用法。可以看某站的源码也是携带大量的context。

为什么会需要context

如果你用过Go写过http。基本上几行代码就可以起来一个server。

在这个server里面,通常一个require就会启动至少一个goroutine来工作;注意是至少一个goroutine。

这些goroutine需要共享这个require的基本数据。例如token,处理require的最大时间(超时才返回数据,请求方超时请求不到)等等。还有就是这么个场景,请求方只是点错了,来了界面,然后立刻关闭了。这样就要快速释放掉创建的goroutine。因为他们已经没用了,他们的结果已经不被需要。当所有的goroutine退出,操作系统就能回收掉这些资源。

还有就是 在Go中server是个“携程模型”,也就是至少一个携程对应处理一个请求。我本人的真实经历(测试环境还好。没造成影响。):再测试的时候,并发访问。某个处理模块慢了,当前系统的请求没有控制,然后超时时间也没有设置。那样等着的goroutine的越来越多。虽然Go官方号称一个goroutine大概是2KB的消耗。但是吧。。看proof的时候 gorouitne达到10W个。内存飙涨。服务不可用。操作系统load飙升。整个服务对外不可用。如果是生产基本就是P0事故。基本就要提桶跑路。

后面我改掉代码。通过设置timeout就避免这个问题。我给请求其他模块的时间设置到Xs.如果超过这个时间没有receive。就直接给请求方一个err或者服务器繁忙。

概括一下:在Go中,我们不能直接killgoroutine,携程的关闭基本就是靠return,Channel。但是在某些情景下面,像我上面说的一个require生成很多子携程,互相之间有关联。需要共享global data。在用channel就挺难操作。

context 用来解决goroutine之间的 退出通知 元数据传递

context底层实现原理

Go 版本 1.13.1

整体概览:

context包的代码量并不是很多。算上注释也就不到4 500行。真实用的代码估计不到200行。这玩意还是挺有意思的。

367r2uR.jpg!web

网上抄了个context的包的具体内容。

um63eav.jpg!web

context的接口

在pre_go19.go这个文件中定义的context接口

type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}Err() error
Value(key interface{}) interface{}}复制代码

Context时是个interface。定义4个func。都是幂等。也就是说多次调用一个method。得到结果是一样的。

第一方法Done().返回一个channel,可以表示context被去取消的信号:当这个channel被关闭/取消,说明context被取消。注意,这就是个RO的channel。Go基础,读取一个关闭的channel只会读到这个管道对应的类型的0值。也就是可以认为 是个<-channel  类型的channel。因此子携程里读这个channel。除非被close掉。否则没有任何东西能取到。也就是可以利用这个特点:从字携程取到0值。就可以做收尾,快速退出。回收资源。

其他的下次在写吧。挺晚了。20200614 23.40。:pray:

欢迎关注我们的微信公众号,每天学习Go知识

FveQFjN.jpg!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK