3.2 平滑关闭与重启

3.2.1 平滑关闭

平滑关闭是指服务进程在退出前的指定时间内完成以下收尾工作:

  1. 关闭所有打开的监听器
  2. 关闭所有空闲连接
  3. 等待所有连接变成空闲状态

注: 该功能不会尝试关闭或等待被劫持连接(如WebSockets),用户应该单独处理这些长连接(方法见3.2.3)

各系统平台均支持平滑关闭功能,使用也非常简单。

假设进程ID为1234,则用户可以通过以下命令执行平滑关闭:

  1. kill 1234

或者在faygo的cmd运行窗口中执行(Windows没有kill命令,只有这一种方式)

  1. Ctrl+c

用户可以通过http请求来回调faygo.Shutdown()函数平滑关闭当前进程,Handler的示例代码如下:

  1. type Shutdown struct {
  2. Second int64 `param:"<in:query> <desc:shutdown timeout /second>"`
  3. }
  4. // Implement the handler interface
  5. func (s *Shutdown) Serve(ctx *faygo.Context) error {
  6. go faygo.Shutdown(time.Duration(s.Second) * time.Second)
  7. return ctx.String(200, "Shuting down...")
  8. }

伪请求示例:

  1. http://localhost:8080/shoutdown?second=10

3.2.2 平滑重启

平滑重启又叫平滑升级、优雅重启,假设进程ID为1234,执行如下几个步骤:

1. 如需升级服务则用新的可执行文件替换老的可执行文件,如只需优雅重启则跳过这一步

2. 通过pid给正在运行的老进程发送特定的信号

  1. kill -USR2 1234

3. 正在运行的老进程,接收到指定的信号后,以子进程的方式启动新的可执行文件并开始处理新请求

4. 老进程执行平滑关闭

5. 新进程在父进程退出后,会被init进程领养,并继续提供服务

注:

  • Windows系统暂不支持该功能
  • 与平滑关闭相同,用户需要单独处理被劫持连接(如WebSockets)或其他长连接以达到平滑关闭老进程的目的(方法见3.2.3)

非Windows系统下,用户可以通过http请求来回调faygo.Reboot()函数进行重启操作,Handler示例代码如下:

  1. type Reboot struct {
  2. Second int64 `param:"<in:query> <desc:shutdown old process timeout /second>"`
  3. }
  4. // Implement the handler interface
  5. func (s *Reboot) Serve(ctx *faygo.Context) error {
  6. go faygo.Reboot(time.Duration(s.Second) * time.Second)
  7. return ctx.String(200, "Rebooting...")
  8. }

伪请求示例:

  1. http://localhost:8080/reboot?second=10

3.2.3 平滑关闭的回调函数

因为项目进程在平滑关闭时不会尝试关闭或等待被劫持连接(如WebSockets)或其他长连接,另外用户也可能有些其他收尾工作要执行,所以faygo提供了一个回调函数来解决该问题。

回调函数的声明:

  1. func SetShutdown(timeout time.Duration, finalizers ...func() error)

使用示例:

  1. func main() {
  2. // 设置进程平滑关闭的时限及自定义收尾函数
  3. faygo.SetShutdown(time.Minute, func() error {
  4. faygo.Debug("finalizer 等待5s...")
  5. time.Sleep(5 * time.Second)
  6. faygo.Debug("finalizer 5s到时!")
  7. return nil
  8. })
  9. ...
  10. app1 := faygo.New("myapp1", "1.0")
  11. app2 := faygo.New("myapp2", "2.0")
  12. ...
  13. // 启动所有服务
  14. faygo.Run()
  15. }