关于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 协议》,转载必须注明作者和本文链接
biubiubiu
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!