什么是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
进程。