一 准備
- Go版本是1.8,使用http.Server內置的Shutdown()方法進行優雅關閉
- Go版本低於1.8的請自行查閱資料,有很多庫可以使用
一 實例
main.go
package main import ( "github.com/gin-gonic/gin" "log" "net/http" "os" "os/signal" "syscall" "time" "context" ) func main(){ router := gin.Default() // v1 r1 := router.Group("/test/v1.0") { r1.GET("/testrestart", controller.Testshutdown) }//router.Run( utils.GlobalObject.ServiceHost + ":" + utils.GlobalObject.ServicePort) srv := &http.Server{ Addr: utils.GlobalObject.ServiceHost + ":" + utils.GlobalObject.ServicePort, Handler: router, } go func() { // service connections if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("listen: %s\n", err) } }() // Wait for interrupt signal to gracefully shutdown the server with // a timeout of 5 seconds. quit := make(chan os.Signal) // kill (no param) default send syscanll.SIGTERM // kill -2 is syscall.SIGINT // kill -9 is syscall. SIGKILL but can"t be catch, so don't need add it signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutdown Server ...") ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server Shutdown:", err) } // catching ctx.Done(). timeout of 5 seconds. select { case <-ctx.Done(): log.Println("timeout of 10 seconds.") } log.Println("Server exiting") }
controller.go
package controller import ( "fmt" "github.com/gin-gonic/gin" "net/http" "time" ) func Testshutdown(ctx *gin.Context){ fmt.Println("testrestart start") time.Sleep(7*time.Second) fmt.Println("testrestart ent") }
瀏覽器訪問http://localhost:8080/test/v1.0/testshutdown
緊接着,立即ctrl+c退出go服務程序
我們會發現,服務程序開始退出了,而瀏覽器依舊在執行,直到7s后,瀏覽器運行完成。
再過3s (總計10s緩沖),go程序的defer程序執行完成,實現了平滑關閉。
下一章我們將一起研究golang的熱加載、熱部署等