什么是graceful restart
能够优雅的重启,可以处理未处理完的request, 保证服务不中断
graceful restart需要做的事
- 重启服务期间可以确保待处理的request能够得到处理(完成或超时)
- 不关闭已经打开的socket连接(重用socket)
endless的实现思路

- 通过
endlessListener重载http.Server.Accept(), 每接收一下request,sync.WaitGroup.Add(1) - 通过
endlessConn重载http.conn.Close(), 当一个request被处理,sync.WaitGroup.Done() endlessServer.Serve()通过sync.WaitGroup.Wait()等待所有已接收的request处理完毕- 当接收到
SINGHUP信号时,fork一个子进程,将当前运行的程序重新执行,并通过环境变量ENDLESS_CONTINUE=1来告知这是子进程。当检测到是子进程时,通过syscall.Kill(syscall.Getppid(), syscall.SIGTERM)来关闭父进程 - 协程
handleSignals通过for循环监听到SIGINT或SIGTERM信号,shutdown endlessServer, close endLessListener, 此时退出http.Server.Serve()的for循环,执行srv.wg.Wait() - 等待父进程处理完所有request,或者通过
endlessServer.hammerTime(), sleep指定时间后,for循环调用WaitGroup.Done(),强制结束
测试
fvbock/endless提供了example, 按照文档所说去一步步执行,可以观察到预料的实验现象。 注意kill -1 $pid 是指发送HUP信号到$pid进程。
kill时的数字对应信号信息如下:
所以很容易理解kill -9 $pid强制杀死$pid进程其实就是发送KILL信号给$pid进程。