前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker Graceful Shutdown

Docker Graceful Shutdown

原创
作者头像
code-x
发布2023-07-10 10:35:17
1660
发布2023-07-10 10:35:17
举报
文章被收录于专栏:code-xcode-x

有几个前提

  1. 操作系统层面: 提供了 kill -9 (SIGKILL)和 kill -15(SIGTERM) 两种停机策略. SIGKILL 信号是一个不能被阻塞、处理或忽略的信号,它会立即终止目标进程. SIGTERM 信号是一个可以被阻塞、处理或忽略的信号,它也可以通知目标进程终止,但是它相对于 SIGKILL 信号来说更加温和,目标进程可以在接收到 SIGTERM 信号时进行一些清理操作,例如保存数据、关闭文件、释放资源等,然后再终止进程
  2. 语言层面: 在Java中, Runtime 类的 addShutdownHook 方法注册 shutdown hook. spring-boot已经实现了. 我们只要找个类实现java.io.Closeable接口的close方法, 再将其注册到容器中即可
  3. 在 Docker 中,执行 docker stop 命令时,它会向容器中的主进程 (pid=1)发送 SIGTERM 信号. 如果容器中的进程不响应 SIGTERM 信号,Docker 会等待一定的时间(默认为 10 秒),然后向容器中的所有进程发送 SIGKILL 信号,以强制结束容器中的进程. 如果我们需要修改 SIGTERM 信号等待的时间,可以在 docker run 命令中使用 --stop-timeout 参数来更改默认的停止超时时间(单位: s)

  1. 当使用kill, stop等命令时, 需要发送SIGTERM信号
  2. 你的进程要正常接收到信号
  3. 你的应用要正常处理信号
应用要正常处理信号

SpringBoot已经做了相关处理, 我们只要实现接口即可

实现org.springframework.context.SmartLifecycle接口, 实现getPhase/start/stop/isRunning方法, 通过getPhase方法定义优先级

代码语言:javascript
复制
@Override
public int getPhase() {
    //在 WebServerGracefulShutdownLifecycle 那一组之后
    return SmartLifecycle.DEFAULT_PHASE - 1;
}
进程要正常接收到信号

容器中只有pid=1的进程才能接收到信号, 所以要保证java的pid=1, dockerfile如下

代码语言:javascript
复制
...
ENV JAVA_OPTS=""
ENV APP_OPTS=""
# 如果用这个格式 sh -c start.sh 会导致pid不为1
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar $APP_OPTS /root/user-web.jar"]

这样, 你的java在容器内的pid就是为1了

日志如下

代码语言:javascript
复制
08:59:04.373 [main    ] INFO  com.thy.backend.user.service.user.web.UserWebApplication     : Starting UserWebApplication v1.0-SNAPSHOT using Java 17.0.2 with PID 1 (/root/user-web.jar started by root in /)

还可以使用https://github.com/krallin/tini/, 将java进程当成tini的子进程执行并执行信号转发

执行docker stop xxx

代码语言:javascript
复制
@Override
public void stop() {
    // 输出
    log.info("stop");
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 应用要正常处理信号
  • 进程要正常接收到信号
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档