官閘道器於重啟的例子優雅地重啟或停止 | 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 協議》,轉載必須註明作者和本文連結