正确使用‘trap指令’实现Docker优雅退出
一般应用(比如mariadb)都会有一个退出命令,用户使用类似systemctl stop ****.service方法,停止其服务时,systemd会调用其配置文件注册的退出命令,该命令执行清理资源、退出集群、输出必要日志等操作后才杀死自己的进程;在系统shutdown的时候也会有类似的流程,最大程度的保证应用正常退出,下面我们称之为“进程优雅退出”。
将应用Docker化后,一个突出的问题是,如何让进程优雅的退出,而不是强行杀死进程。Docker stop和Docker kill分别实现了优雅退出和强行退出两个操作:
Docker stop:向容器内1号进程,发送SIGTERM信号,在10S之后(可通过参数指定)再发送SIGKILL信号。
Docker kill:直接发送SIGKILL信号。
显然Docker已经考虑到应用优雅退出的问题,但在实际使用中,会遇到下面2个困难:
1. 只有1号进程才收到SIGTERM信号,但Docker中有很多1号进程为monitor或者为初始化脚本的进程,并不是工作进程,且1号进程不能处理SIGTERM信号,以mariadb为例,容器内的进程关系如下:
1 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm://
2 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql/ ...
其中2号进程为1号进程的子进程,虽然2号进程可以处理SIGTERM信号但其收不到该信号,而1号进程虽然能收到SIGTERM但并不能处理此信号。
2. 即使1号进程能处理SIGTERM信号,但若其有子进程为外部命令(非build in命令),且子进程为前台阻塞状态,那么1号进程在直到子进程退出前仍然不能收到SIGTERM信号。如下bash是不会处理SIGTERM信号的:
#!/bin/bash
trap 'exit 0' SIGTERM
sleep
关于这一点需要了解进程处理信号的限制:只有当进程阻塞在内建命令时才可以响应SIG信号,否则会一直等待子进程退出后再处理,如上面的bash,要等到10000秒之后才能处理SIGTERM。关于内建命令和外部命令,描述如下:
内部命令实际上是shell程序的一部分,shell不需要创建子进程,比如:exit,history,cd,echo,wait,trap等,linux系统加载运行时shell就被加载并驻留在系统内存中,一般不会fork子进程。
外部命令是linux系统中的实用程序部分,需要时才将其调用内存。一般会fork出子进程。
用type命令可以分辨内部命令与外部命令。
综上所述,对于多进程Docker,我建议在容器中使用自定义bash脚本作为容器入口,脚本中使用后台方式执行具体应用的命令,然后使用内建wait阻塞,并通过trap指令监听SIGTERM,执行应用退出操作,下面以容器化mariadb为例,描述其脚本的大概实现:
#!/bin/bash
trap 'mysqladmin -uroot -p123456 shutdown' SIGTERM
mysqld_safe --wsrep-cluster-address=gcomm://10.158.113.207,10.158.113.80,10.158.113.79 &
wait $!
以上述脚本为入口的maraidb容器内进程关系如下:
mysql 1 0.0 0.0 11628 1352 ? Ss+ 07:59 0:00 /bin/bash /usr/bin/test.sh
mysql 9 0.0 0.0 11764 1636 ? S+ 07:59 0:00 /bin/sh /usr/bin/mysqld_safe --wsrep-cluster-address=gcomm://10.158.113.207,10.158.113.80,10
mysql 188 1.0 3.7 1087368 300168 ? Sl+ 07:59 0:16 \_ /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/p
当执行docker stop ***的时候,该容器会自动调用mysqladmin shutdown优雅退出。
以上为个人原创,欢迎转发,并保留出处。
个人能力有限,错误之处请留言指出。
正确使用‘trap指令’实现Docker优雅退出的更多相关文章
- Node 出现 uncaughtException 之后的优雅退出方案
Node 的异步特性是它最大的魅力,但是在带来便利的同时也带来了不少麻烦和坑,错误捕获就是一个.由于 Node 的异步特性,导致我们无法使用 try/catch 来捕获回调函数中的异常,例如: try ...
- NodeJS服务器退出:完成任务,优雅退出
上一篇文章,我们通过一个简单的例子,学习了NodeJS中对客户端的请求(request)对象的解析和处理,整个文件共享的功能已经完成.但是,纵观整个过程,还有两个地方明显需要改进: 首先,不能共享完毕 ...
- golang channel详解和协程优雅退出
非缓冲chan,读写对称 非缓冲channel,要求一端读取,一端写入.channel大小为零,所以读写操作一定要匹配. func main() { nochan := make(chan int) ...
- golang中使用Shutdown特性对http服务进行优雅退出使用总结
golang 程序启动一个 http 服务时,若服务被意外终止或中断,会让现有请求连接突然中断,未处理完成的任务也会出现不可预知的错误,这样即会造成服务硬终止:为了解决硬终止问题我们希望服务中断或退出 ...
- .NET Worker Service 如何优雅退出
上一篇文章中我们了解了 .NET Worker Service 的入门知识[1],今天我们接着介绍一下如何优雅地关闭和退出 Worker Service. Worker 类 从上一篇文章中,我们已经知 ...
- .NET Worker Service 作为 Windows 服务运行及优雅退出改进
上一篇文章我们了解了如何为 Worker Service 添加 Serilog 日志记录,今天我接着介绍一下如何将 Worker Service 作为 Windows 服务运行. 我曾经在前面一篇文章 ...
- 优雅退出在Golang中的实现
背景 为什么需要优雅关停 在Linux下运行我们的go程序,通常有这样2种方式: 前台启动.打开终端,在终端中直接启动某个进程,此时终端被阻塞,按CTRL+C退出程序,可以输入其他命令,关闭终端后程序 ...
- Docker 优雅终止方案
作为一名系统工程师,你可能经常需要重启容器,毕竟Kubernetes的优势就是快速弹性伸缩和故障恢复,遇到问题先重启容器再说,几秒钟即可恢复,实在不行再重启系统,这就是系统重启工程师的杀手锏.然而现实 ...
- 优雅退出 Android 应用程序的 6 种方式
我们先来看看几种常见的退出方法(不优雅的方式) 一.容器式 建立一个全局容器,把所有的Activity存储起来,退出时循环遍历finish所有Activity import java.util.Arr ...
随机推荐
- pandas关联mysql并读写数据库
1.代码读写mysql,必须安装关联mysql的工具 操作如下命令: sudo apt-get install mysql-server mysql-clientsudo apt-get instal ...
- Jenkins注意点
这里要填写 在 Linux 上 生成的 git 私钥 并且带上 前后 注释 ------start ----- ---end -------
- Voyager下的Settings方法
设置网站标题,logo,描述: 自定义setting字段,添加group为文章,key为title的字段: 添加成功: 前端页面写法: <img src="{{ Voyager::im ...
- 解析Vue.js中的computed工作原理
我们通过实现一个简单版的和Vue中computed具有相同功能的函数来了解computed是如何工作的.写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指 ...
- 【php】对象的比较
对象的比较 相等的比较 ==当使用比较运算符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等. 全等的比较 ===如果 ...
- python爬虫基础15-python图像处理,PIL库
Python图像处理-Pillow 简介 Python传统的图像处理库PIL(Python Imaging Library ),可以说基本上是Python处理图像的标准库,功能强大,使用简单. 但是由 ...
- machine_desc
每一个machine,都要定义一个自己的machine_desc结构,该结构定义了该machine的一些最基本的特性. struct machine_desc { unsigned int nr; / ...
- SDUSToj第十一次作业源代码格式问题
Problem I: 源代码的格式 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 1471 Solved: 634 [Submit][Status][W ...
- Linux学习-systemctl 针对 timer 的配置文件
如何使用 systemd 内建的 time 来处理各种任务呢? systemd.timer 的优势 在 archlinux 的官网 wiki 上面有提到,为啥要使用 systemd.timer 呢? ...
- Mime类型与文件后缀对照表及探测文件MIME的方法
说明:刚刚写了一篇<IHttpHandler的妙用(2):防盗链!我的资源只有我的用户才能下载>的文章,网址:http://blog.csdn.net/zhoufoxcn/archive/ ...