3.2 平滑关闭与重启
3.2.1 平滑关闭
平滑关闭是指服务进程在退出前的指定时间内完成以下收尾工作:
- 关闭所有打开的监听器
- 关闭所有空闲连接
- 等待所有连接变成空闲状态
注: 该功能不会尝试关闭或等待被劫持连接(如WebSockets),用户应该单独处理这些长连接(方法见3.2.3)
各系统平台均支持平滑关闭功能,使用也非常简单。
假设进程ID为1234,则用户可以通过以下命令执行平滑关闭:
kill 1234
或者在faygo的cmd运行窗口中执行(Windows没有kill命令,只有这一种方式)
Ctrl+c
用户可以通过http请求来回调faygo.Shutdown()函数平滑关闭当前进程,Handler的示例代码如下:
type Shutdown struct {
Second int64 `param:"<in:query> <desc:shutdown timeout /second>"`
}
// Implement the handler interface
func (s *Shutdown) Serve(ctx *faygo.Context) error {
go faygo.Shutdown(time.Duration(s.Second) * time.Second)
return ctx.String(200, "Shuting down...")
}
伪请求示例:
http://localhost:8080/shoutdown?second=10
3.2.2 平滑重启
平滑重启又叫平滑升级、优雅重启,假设进程ID为1234,执行如下几个步骤:
1. 如需升级服务则用新的可执行文件替换老的可执行文件,如只需优雅重启则跳过这一步
2. 通过pid给正在运行的老进程发送特定的信号
kill -USR2 1234
3. 正在运行的老进程,接收到指定的信号后,以子进程的方式启动新的可执行文件并开始处理新请求
4. 老进程执行平滑关闭
5. 新进程在父进程退出后,会被init进程领养,并继续提供服务
注:
- Windows系统暂不支持该功能
- 与平滑关闭相同,用户需要单独处理被劫持连接(如WebSockets)或其他长连接以达到平滑关闭老进程的目的(方法见3.2.3)
非Windows系统下,用户可以通过http请求来回调faygo.Reboot()函数进行重启操作,Handler示例代码如下:
type Reboot struct {
Second int64 `param:"<in:query> <desc:shutdown old process timeout /second>"`
}
// Implement the handler interface
func (s *Reboot) Serve(ctx *faygo.Context) error {
go faygo.Reboot(time.Duration(s.Second) * time.Second)
return ctx.String(200, "Rebooting...")
}
伪请求示例:
http://localhost:8080/reboot?second=10
3.2.3 平滑关闭的回调函数
因为项目进程在平滑关闭时不会尝试关闭或等待被劫持连接(如WebSockets)或其他长连接,另外用户也可能有些其他收尾工作要执行,所以faygo提供了一个回调函数来解决该问题。
回调函数的声明:
func SetShutdown(timeout time.Duration, finalizers ...func() error)
使用示例:
func main() {
// 设置进程平滑关闭的时限及自定义收尾函数
faygo.SetShutdown(time.Minute, func() error {
faygo.Debug("finalizer 等待5s...")
time.Sleep(5 * time.Second)
faygo.Debug("finalizer 5s到时!")
return nil
})
...
app1 := faygo.New("myapp1", "1.0")
app2 := faygo.New("myapp2", "2.0")
...
// 启动所有服务
faygo.Run()
}