Last updated
Last updated
并发安全的传递上下文,如传递 trace_id、kv 结构等
树状并发情景中的协程控制(某层任务取消后,及时停止所有的下层任务,上层不受影响;减少额外资源的消耗,减少处理时长)
超时控制
为啥不将这里的 canceler
接口与 Context
接口合并,而是分成两个方法呢?他们定义的方法中都有 Done
方法。可以解释得通的说法是,源码作者认为 cancel
方法并不是 Context
必须的,根据最小接口设计原则,将两者分开。像 emptyCtx
和 valueCtx
不是可取消的,所以他们只要实现 Context
接口即可。
库里头提供了4个 Context
实现,来供大家玩耍
其实主要就做了一件事:close(c.done)
把 c.done
这个 channel
关闭掉,这样所有通过 select
方法监听 <- c.Done()
的协程都会收到通知
WithDeadline
内置了 timer
定时器,到期就执行 cancel
Withtimeout
实际上是 Withdeadline
的语法糖,使用 timeout
参数算了下 deadline
而已
首先 Server
在开启服务时会创建一个 valueCtx
, 存储了server
的相关信息,之后每建立一条连接就会开启一个协程,并携带此valueCtx
。
建立连接之后会基于传入的context
创建一个valueCtx
用于存储本地地址信息,之后在此基础上又创建了一个cancelCtx
,然后开始从当前连接中读取网络请求,每当读取到一个请求则会将该cancelCtx
传入,用以传递取消信号。一旦连接断开,即可发送取消信号,取消所有进行中的网络请求。
读取到请求之后,会再次基于传入的context
创建新的cancelCtx
,并设置到当前请求对象req
上,同时生成的response
对象中cancelCtx
保存了当前context
取消的方法。
在整个server
处理流程中,使用了一条 context
链贯穿Server
、Connection
、Request
,不仅将上游的信息共享给下游任务,同时实现了上游可发送取消信号取消所有下游任务,而下游任务自行取消不会影响上游任务。
另外有两点值得注意:
context
的取消是柔性的,上游任务仅仅使用 context
通知下游不再需要,不会直接干涉和中断下游任务的执行,由下游任务自行处理取消逻辑,下游自己写 select <- ctx.Done()
的逻辑。
context
是线程安全的,其本身是不可变的(immutable),且并发情况下会加锁。
是 Go 语言在 1.7 版本中引入标准库的接口,该接口定义了四个需要实现的方法,其中包括: