Golang 服務優雅重啟


很多時候對於服務升級的做法簡單粗暴, 就簡單的殺進程啟動新的進程.

還有的好一點就是多個相同的服務依次升級, 保證有服務可用. 但是公平的說這兩種都會丟失請求中的連接.

鑒於這種情況, 在現實中我們可以使用優雅重啟來搞定這個問題. Golang 實現優雅重啟的原理也很簡單:

  • 監聽 USR2 信號;

  • 收到信號后將服務監聽的文件描述符傳遞給新的子進程;

  • 此時新老進程同時接收請求;

  • 父進程停止接收新請求, 等待舊請求完成(或超時);

  • 父進程退出.

對於上面的原理看似簡單, 其實是分成了兩個大的要點:

  • 新老進程同時監聽同一端口, 這個很簡單, Go 很早舊支持;

  • 如何等待舊的請求完成, 這個在 Go 1.8 (新增了Server.Shutdown) 之前是需要費一番功夫的.

我們搞定了上面的原理之后, 加上 Go 1.8 的完美等待舊請求的實現,

我實現了一個簡單的優雅重啟庫: https://github.com/douglarek/zerodown.

zerodown 完美兼容基於 Go 標准庫 Server 監聽服務.

對於標准庫的使用, 我們可以象下面一樣使用:

package main import ( "fmt" "log" "net/http" "time" "github.com/douglarek/zerodown" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { time.Sleep(5 * time.Second) fmt.Fprintln(w, "Hello, World!") }) log.Fatalln(zerodown.ListenAndServe(":8080", nil))

對於第三方庫 Gin 我們可以:

package main

import ( "log" "net/http" "time" "github.com/douglarek/zerodown" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.GET("/", func(c *gin.Context) { time.Sleep(5 * time.Second) c.String(http.StatusOK, "Hello, World!") }) log.Fatalln(zerodown.ListenAndServe(":8080", router)) }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM