如何优雅地关闭运行在Docker容器中的Go服务器?

问题描述 投票:0回答:1

现在,一个用 Go 编写的 Web 服务器正在 docker 容器中运行。 当停止 docker 容器执行

docker stop
命令时,我想优雅地关闭 Web 服务器。 这种情况下,是否可以像下面这样执行优雅关机呢?

当前代码


ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM) // I don't know what signal to catch
defer stop()

srv := &http.Server{
    Addr:    port,
    Handler: mux,
}

go srv.ListenAndServe()

<-ctx.Done()

// do someshing

log.Println("server will shutdown gracefully.")

err = srv.Shutdown(ctx)
if err != nil {
    return err
}


docker go signals graceful-shutdown
1个回答
0
投票

SIGTERM
是要收听的正确信号。然而,您的代码可以进行一些改进。

  1. 不要忽略
    ListenAndServe()
    的返回值(可能是
    context.Canceled
    ,但不一定是)。
  2. 不要向
    Shutdown()
    提供已取消的上下文。如果这需要太多时间,我们将受到
    SIGKILL
    我们实际上不会收到的信号)的影响,所以我们可以只提供
    context.Background()

这为我们提供了以下信息:

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGTERM)
defer stop()

srv := &http.Server{
    Addr:    port,
    Handler: mux,
}

go func() {
    err := srv.ListenAndServe()
    log.Printf("ListenAndServe() returned: %v", err)
}()

<-ctx.Done()

log.Println("server will shutdown gracefully.")

return srv.Shutdown(context.Background())

重要的一点是,

Shutdown()
将耐心等待活动连接,该连接可能会也可能不会及时完成。也可以在处理程序中使用
signal.NotifyContext()
,尝试快速完成剩余工作,以防收到
SIGTERM
。我建议改为向
--time
提供适当的
docker container stop
参数(以防默认 10 秒不够)。

© www.soinside.com 2019 - 2024. All rights reserved.