优雅关机重启

169 阅读1分钟
  • 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式

优雅地关机或重启 | 李文周的博客 (liwenzhou.com)

srv := &http.Server{
   Addr:    fmt.Sprintf(":%d", settings.Conf.Port),
   Handler: r,
}

go func() {
   // 开启一个goroutine启动服务
   if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
      log.Fatalf("listen: %s\n", err)
   }
}()

// 等待中断信号来优雅地关闭服务器,为关闭服务器操作设置一个5秒的超时
quit := make(chan os.Signal, 1) // 创建一个接收信号的通道
// kill 默认会发送 syscall.SIGTERM 信号
// kill -2 发送 syscall.SIGINT 信号,我们常用的Ctrl+C就是触发系统SIGINT信号
// kill -9 发送 syscall.SIGKILL 信号,但是不能被捕获,所以不需要添加它
// signal.Notify把收到的 syscall.SIGINT或syscall.SIGTERM 信号转发给quit
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // 此处不会阻塞
<-quit                                               // 阻塞在此,当接收到上述两种信号时才会往下执行
zap.L().Info("Shutdown Server ...")
// 创建一个5秒超时的context
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// 5秒内优雅关闭服务(将未处理完的请求处理完再关闭服务),超过5秒就超时退出
if err := srv.Shutdown(ctx); err != nil {
   zap.L().Fatal("Server Shutdown", zap.Error(err))
}

image.png

当我们按下ctrl+c的时候发送一个syscall.sigint信号,这是创建的channel就会收到这个信号,然后创建一个5s超时的context。。调用hettp自带的优雅关机函数shutdown, 5秒内优雅关闭服务(将未处理完的请求处理完再关闭服务),超过5秒就超时退出