<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們編寫的Web專案部署之後,經常會因為需要進行設定變更或功能迭代而重啟服務,單純的kill -9 pid的方式會強制關閉程序,這樣就會導致伺服器端當前正在處理的請求失敗,那有沒有更優雅的方式來實現關機或重啟呢?
閱讀本文需要了解一些UNIX系統中訊號的概念,請提前查閱資料預習。
優雅關機就是伺服器端關機命令發出後不是立即關機,而是等待當前還在處理的請求全部處理完畢後再退出程式,是一種對使用者端友好的關機方式。而執行Ctrl+C
關閉伺服器端時,會強制結束程序導致正在存取的請求出現問題。
Go 1.8版本之後, http.Server 內建的 Shutdown() 方法就支援優雅地關機,具體範例如下:
// +build go1.8 package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "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, "Welcome Gin Server") }) srv := &http.Server{ Addr: ":8080", Handler: router, } go func() { // 開啟一個goroutine啟動服務 if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %sn", err) } }() // 等待中斷訊號來優雅地關閉伺服器,為關閉伺服器操作設定一個5秒的超時 quit := make(chan os.Signal, 1) // 建立一個接收訊號的通道 // kill 預設會傳送 syscall.SIGTERM 訊號 // kill -2 傳送 syscall.SIGINT 訊號,我們常用的Ctrl+C就是觸發系統SIGINT訊號 // kill -9 傳送 syscall.SIGKILL 訊號,但是不能被捕獲,所以不需要新增它 // signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 訊號轉發給quit signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此處不會阻塞 <-quit // 阻塞在此,當接收到上述兩種訊號時才會往下執行 log.Println("Shutdown Server ...") // 建立一個5秒超時的context ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // 5秒內優雅關閉服務(將未處理完的請求處理完再關閉服務),超過5秒就超時退出 if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown: ", err) } log.Println("Server exiting") }
如何驗證優雅關機的效果呢?
上面的程式碼執行後會在原生的8080埠開啟一個web服務,它只註冊了一條路由/
,後端服務會先sleep 5秒鐘然後才返回響應資訊。
我們按下Ctrl+C時會傳送syscall.SIGINT來通知程式優雅關機,具體做法如下:
Ctrl+C
命令給程式傳送syscall.SIGINT
訊號優雅關機實現了,那麼該如何實現優雅重啟呢?
我們可以使用 fvbock/endless 來替換預設的 ListenAndServe
啟動服務來實現, 範例程式碼如下:
package main import ( "log" "net/http" "time" "github.com/fvbock/endless" "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 gin!") }) // 預設endless伺服器會監聽下列訊號: // syscall.SIGHUP,syscall.SIGUSR1,syscall.SIGUSR2,syscall.SIGINT,syscall.SIGTERM和syscall.SIGTSTP // 接收到 SIGHUP 訊號將觸發`fork/restart` 實現優雅重啟(kill -1 pid會傳送SIGHUP訊號) // 接收到 syscall.SIGINT或syscall.SIGTERM 訊號將觸發優雅關機 // 接收到 SIGUSR2 訊號將觸發HammerTime // SIGUSR1 和 SIGTSTP 被用來觸發一些使用者自定義的hook函數 if err := endless.ListenAndServe(":8080", router); err!=nil{ log.Fatalf("listen: %sn", err) } log.Println("Server exiting") }
如何驗證優雅重啟的效果呢?
我們通過執行kill -1 pid
命令傳送syscall.SIGINT
來通知程式優雅重啟,具體做法如下:
hello gin!
修改為hello q1mi!
,再次編譯go build -o graceful_restarthello gin!
後再次存取127.0.0.1:8080/會收到hello q1mi!
的響應。但是需要注意的是,此時程式的PID變化了,因為endless
是通過fork
子程序處理新請求,待原程序處理完當前請求後再退出的方式實現優雅重啟的。所以當你的專案是使用類似supervisor
的軟體管理程序時就不適用這種方式了。
無論是優雅關機還是優雅重啟歸根結底都是通過監聽特定系統訊號,然後執行一定的邏輯處理保障當前系統正在處理的請求被正常處理後再關閉當前程序。使用優雅關機還是使用優雅重啟以及怎麼實現,這就需要根據專案實際情況來決定了。
以上就是使用golang如何優雅的關機或重啟 的詳細內容,更多關於golang關機重啟 的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45