docker容器优雅停机

我们部署在docker中的springboot程序在docker停止的时候并没有执行shutdownHook的操作,正常在本地idea停止springboot服务会看到一系列的shutdownHook操作日志

日志如下:

2021-05-13 11:12:29.253 INFO  218 [,] [SpringContextShutdownHook] o.s.s.c.ThreadPoolTaskScheduler Shutting down ExecutorService 'catalogWatchTaskScheduler'
2021-05-13 11:12:29.261 INFO  96 [,] [Thread-694] c.x.j.core.server.EmbedServer >>>>>>>>>>> xxl-job remoting server stop.
2021-05-13 11:12:29.272 INFO  87 [,] [xxl-job, executor ExecutorRegistryThread] c.x.j.c.t.ExecutorRegistryThread >>>>>>>>>>> xxl-job registry-remove success, registryParam:RegistryParam{registryGroup='EXECUTOR', registryKey='shop', registryValue='http://192.168.1.88:9999/'}, registryResult:ReturnT [code=200, msg=null, content=null]
2021-05-13 11:12:29.272 INFO  105 [,] [xxl-job, executor ExecutorRegistryThread] c.x.j.c.t.ExecutorRegistryThread >>>>>>>>>>> xxl-job, executor registry thread destory.
2021-05-13 11:12:29.272 INFO  125 [,] [SpringContextShutdownHook] c.x.j.core.server.EmbedServer >>>>>>>>>>> xxl-job remoting server destroy success.
2021-05-13 11:12:29.273 INFO  99 [,] [xxl-job, executor JobLogFileCleanThread] c.x.j.c.t.JobLogFileCleanThread >>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destory.
2021-05-13 11:12:29.273 INFO  97 [,] [xxl-job, executor TriggerCallbackThread] c.x.j.c.t.TriggerCallbackThread >>>>>>>>>>> xxl-job, executor callback thread destory.
2021-05-13 11:12:29.273 INFO  127 [,] [Thread-693] c.x.j.c.t.TriggerCallbackThread >>>>>>>>>>> xxl-job, executor retry callback thread destory.
2021-05-13 11:12:29.361 INFO  94 [,] [SpringContextShutdownHook] o.s.c.c.s.ConsulServiceRegistry Deregistering service with consul: shop-192-168-1-88-8883
2021-05-13 11:12:29.379 INFO  218 [,] [SpringContextShutdownHook] o.s.s.c.ThreadPoolTaskExecutor Shutting down ExecutorService
2021-05-13 11:12:29.379 INFO  350 [,] [SpringContextShutdownHook] c.z.hikari.HikariDataSource HikariCP - Shutdown initiated...
2021-05-13 11:12:29.387 INFO  352 [,] [SpringContextShutdownHook] c.z.hikari.HikariDataSource HikariCP - Shutdown completed.

启动一个docker容器来验证问题

编写一个Dockerfile

FROM openjdk:8-jre-alpine
COPY ./build/libs/app.jar /app/app.jar
COPY ./docker/bootapp.sh /app/bootapp.sh
WORKDIR /app
EXPOSE 8080
ENTRYPOINT ["./bootapp.sh"]

创建启动脚本bootapp.sh

#!/bin/sh
echo 'Do something'
java -jar app.jar

docker stop 做了什么

docker官网对docker stop的描述:

The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL. The first signal can be changed with the STOPSIGNAL instruction in the container’s Dockerfile, or the --stop-signal option to docker run.

docker stop命令执行的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。在使用docker stop命令的时候,我们唯一能控制的是超时时间,比如设置为20秒超时:

当我们在 shell 中给进程发送 SIGTERMSIGINT 信号的时候,这些进程往往都能正确的处理。但是在 docker 中却不灵了。这是因为在 docker 中,只会将 SIGTERM 等所有的 signal 信号发送给 PID 为 1 的进程,当我们 docker 中运行的进程的PID不是 1 时,就不会收到这样的信号。

如何优雅的关闭容器

通过前面的内容,我们已经了解了容器没有被优雅关闭的原因和可能导致的问题,接下来,我们来看看如何解决。

使目标进程成为 PID 1

既然 docker 只会将 sigal 发送给 PID 1 的进程,那就让我们的进程成为 PID 1 的进程就好了。

docker 的 exec 与 shell 模式

DockerfileENTRYPOINT 有两种写法,即 execshell

# exec form
ENTRYPOINT ["command", "param"]
# shell form
ENTRYPOINT command param

两者的区别在于:

  • exec 形式的命令会使用 PID 1 的进程
  • shell 形式的命令会被执行为 /bin/sh -c <command>,PID为1的进程是“/bin/sh”,command不会执行在 PID 1 上,也就不会收到 signal

所以,我们应该选择 exec 模式,让我们的程序成为 PID 1 进程。

ENTRYPOINT ["java", "-jar", "app.jar"]

exec 命令

exec 形式的 ENTRYPOINT 只能解决 无需任何准备工作就启动进程 的场景,而不能解决一些需要准备工作的复杂场景。

在这样的场景中,我们的 ENTRYPOINT 往往需要执行一个 shell 脚本:

ENTRYPOINT ["./bootapp.sh"]

然后在这个脚本中执行我们的准备工作,完成后再启动真正的进程。
比如上面的例子,做完准备后,启动 java 进程。
这时候,我们的 java 进程就无法成为 PID 1 进程。

我们可以看到,java 进程的 PID 是 45,也就无法优雅退出了。

为了解决这个问题,我们可以使用 exec 命令来解决。这个命令的作用就是使用新的进程替代原有的进程,并保持 PID 不变
这就意味着我们可以在执行 java 命令的时候使用它,从而替换掉 PID 1 的 shell 脚本:

#!/bin/sh
echo "Do something"
exec java -jar app.jar

shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。

我们再来看一下容器中的进程:

使用 exec 命令之后,我们无论是使用 ctrl+c 还是 docker stop 都能让进程接收到信号,执行相应的操作后退出:

日志表明,java进程收到了 docker stop 发送的 SIGTERM 信号,并且正确的触发了相关操作,最后退出程序。

docker容器优雅停机相关推荐

  1. 腾讯王卡运营坑之一:web容器优雅停机缓慢

    什么叫做优雅停机: 通俗点理解(以tomcat为例),优雅停机就是当tomcat收到停机命令时,tomcat会关闭所有入口(表明我已经要停机了,你们别再来请求我了),同时对已经接受的请求继续完成相应的 ...

  2. Java应用的优雅停机

    一. 优雅停机的概念 优雅停机一直是一个非常严谨的话题,但由于其仅仅存在于重启.下线这样的部署阶段,导致很多人忽视了它的重要性,但没有它,你永远不能得到一个完整的应用生命周期,永远会对系统的健壮性持怀 ...

  3. Spring Boot 2.3.0 新特性:优雅停机!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 前言:关于Spring Boot.Spring Cloud应用的优 ...

  4. SpringBoot 2.3 新特性之优雅停机,这波操作太秀了!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 什么是优雅停机 先来一段简单的代码,如下: @RestContro ...

  5. springboot 优雅停机_Spring Boot 2.3 新特性优雅停机详解

    什么是优雅停机 先来一段简单的代码,如下: @RestControllerpublic class DemoController { @GetMapping("/demo") pu ...

  6. Spring Boot 2.3.0 新特性:优雅停机

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 前言:关于Spring Boot.Spring Clou ...

  7. springboot 优雅停机_新姿势,Spring Boot 2.3.0 如何优雅停机?

    点击上方蓝色字体,选择"设为星标" 优质文章,及时送达 来源 | https://urlify.cn/mu22If 先来一段简单的代码,如下: @RestControllerpub ...

  8. SpringBoot 2.3 新特性之优雅停机

    1 SpringBoot 2.3 新特性之优雅停机 什么是优雅停机 先来一段简单的代码,如下: @RestController public class DemoController {@GetMap ...

  9. Spring Boot(Cloud) 优雅停机

    为了解决在微服务重启的过程中,可能出现一部分 http 请求处理失败的问题,提供一下方案 拟用方案: 第一步:重启前先从主动将服务剔除,并等待一段时间 第二步:停止服务并重启 一.主动将服务剔除 该方 ...

最新文章

  1. 经常使用的eclipse插件
  2. Java线程的等待与唤醒代码示例
  3. [网络安全自学篇] 四十四.Windows远程桌面服务缺陷(CVE-2019-0708)复现及防御详解
  4. Discuz! X2.5 添加自定义数据调用模块
  5. 给学Java的大学生们分享一些经验
  6. 学习jQuery formValidator
  7. mac下编译curl库(处理https的问题)
  8. Leetcode 338.比特位计数
  9. html矩形变圆形的代码,html5canvas绘制矩形和圆形的实例代码.pdf
  10. oracle ebs工单入库,ORACLE-EBS_库存功能点操作模块.doc
  11. window 上 shell 连接工具
  12. jenkins打包后文件通过ssh上传linux服务器配置
  13. excel取末尾数字_Excel公式技巧11: 从字符串中提取数字——数字位于字符串末尾...
  14. Java实现比较APP版本号大小
  15. 财管U08 公司估值 教材笔记
  16. 23王道考研数据操作目录一览
  17. 经典算法研究系列:五、红黑树算法的实现与剖析
  18. android控制中心实现,基于Android平台的智能家居系统控制中心的设计与实现
  19. Python爬虫爬取单张图片
  20. 关于MongoDB使用的优化总结

热门文章

  1. 快鲸写字楼物业管理软件收费标准如何?
  2. Chrome提示:"请停用以开发者模式运行的扩展程序"的解决办法
  3. 拿下宝马中国量产订单的四维图新,如何在自动驾驶地图领域内外兼修?...
  4. 用matlab水和水蒸汽热力性质,新的水和水蒸汽热力性质国际标准IAPWS—IF97及计算软件...
  5. python创建表格怎么只能65536_python写入excel超过65536行报错问题解决方法
  6. 音乐人必备软件-FL studio-Overture-Guitar Pro
  7. Axios-Poly马尔文帕纳科荧光光谱仪电源维修PW4400高压发生器维修
  8. 10KV配电工程电力监控系统的设计及应用
  9. android 删除短信权限,Android删除短信的方法
  10. Pycharm配置——解释器(interpreter)