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