web服务在重启时,正在处理的请求可能会被强制的关闭。这样会影响服务的可用性。所以需要服务优雅退出。
原理就是先停止端口监听,等没有新的请求过来。然后等一两秒然后再停服务。Golang中signal包里的Notify函数支持订阅信号,程序收到信号后自己来控制shutdown的过程。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| func GracefullyStop(f func()) { c := make(chan os.Signal) signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR1) go func() { for s := range c { switch s { case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: fmt.Println("Program Exit...", s) f() case syscall.SIGUSR1: fmt.Println("usr1 signal", s) default: fmt.Println("other signal", s) } } }() select { case <-c: fmt.Printf("service stop") go func() { if _, ok := <-time.After(3); ok { os.Exit(-1) } }() f() } }
func main() { server.Start() GracefullyStop(func() { server.StopListen() _, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() server.Close()
})
}
|