关于gin利用src.Shutdown进行平滑关闭原理分享
官网关于重启的例子优雅地重启或停止 | Gin Web Framework (gin-gonic.com)
gin利用src.Shutdown的关闭的行为可以这么看待,一件是当前是否没有链接了,另一件事情是你传入了一个最大超时时间是否已到,如果到了也停止。结束在这个函数里面的标志,表现在 srv.Shutdown() 返回了结果。
gin 平滑关闭原理
- src.Shutdown 关闭外部连接,
- gin创建了一个定时器
- 检查当前是否还有运行着的连接,如果没有则 return 。
否则如果有进行select操作。 - select 中同时检测两个channel 第一个是 context.WithTimeout ,他会在5s后发送,如果他收到了结果会直接 return
- 另一个是 就是定时器的channel,如果收到的是定时器的 channel ,并不会return,而是进行再一次检查。如果还是有链接存在,就会继续下一轮的select
其中下面凉快代码有助于我们理解它的实现。
这是一段关于context.WithTimeout
的用法,效果是5后可以从channel
收到值(下文中没有取,收到直接抛弃了)
fmt.Println(time.Now().String())
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
<-ctx.Done()
fmt.Println(time.Now().String())
这是一段关于同时等待两个channel
的代码
ch := make(chan int)
ch2 := make(chan int)
go func() {
for i := 5; i > 0; i-- {
time.Sleep(time.Second * 1)
}
ch <- 1
}()
go func() {
time.Sleep(time.Second * 10)
ch2 <- 1
}()
select {
case <-ch:
fmt.Println("收到ch")
break
case <-ch2:
fmt.Println("收到ch2")
break
}
//收到后的操作
源码部分截取
·····
timer := time.NewTimer(nextPollInterval())
defer timer.Stop()
for {
if srv.closeIdleConns() && srv.numListeners() == 0 {
return lnerr
}
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
timer.Reset(nextPollInterval())
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: