一 准备
- 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 ", 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的热加载、热部署等