Docker Swarm环境下如何软重启PHP worker容器 避免中断运行中任务
Docker Swarm下PHP Worker无中断软重启实现方案
以下是完全符合你需求的软重启实现方案,全程不会中断正在运行的任务:
1. 改造PHP Worker脚本,支持信号捕获
首先需要开启PHP的pcntl扩展(处理进程信号),在脚本中捕获Docker停止时默认发送的SIGTERM信号,设置终止标记,等待当前任务处理完成后再退出脚本:
<?php // 开启信号回调检测 declare(ticks = 1); $stopFlag = false; // 捕获SIGTERM信号,设置终止标记 pcntl_signal(SIGTERM, function () use (&$stopFlag) { $stopFlag = true; }); // Gearman Worker初始化逻辑 $worker = new GearmanWorker(); $worker->addServer('你的Gearman服务地址', 4730); $worker->addFunction('你的任务处理方法名', '实际处理任务的函数名'); // 循环逻辑增加终止标记判断 while (!$stopFlag && $worker->work()) { // 处理完当前任务后检查是否需要退出 if ($stopFlag) { // 可在此处增加退出日志、资源释放逻辑 exit(0); } // 无任务时可加短休眠降低CPU占用 usleep(100000); }
Debian10环境下可直接通过apt install php7.4-pcntl安装扩展。
2. 配置Docker优雅停止参数
Docker默认停止容器时只会等待10秒,之后就会发送SIGKILL强制终止进程,需要调整宽限期匹配你的任务最长执行时长:
- 在Dockerfile中增加配置:
STOPSIGNAL SIGTERM,明确容器停止时发送的信号为SIGTERM - 启动/更新Service时增加
--stop-grace-period 300s参数,将宽限期设为5分钟(可根据你的任务最大执行时长调整)
3. 执行软重启操作
因为你仅需要更新PHP脚本、不需要更换镜像,建议将PHP脚本目录通过bind mount挂载到宿主机,先更新宿主机上的脚本文件,再执行以下两种操作任选其一即可:
方案A:批量滚动软重启(适合多副本场景)
docker service update \ --update-parallelism 2 \ # 每次同时重启2个容器,可根据总副本数调整 --update-delay 10s \ # 每批重启的间隔时间,保证前一批容器正常退出重启完成 --stop-grace-period 300s \ PHP-worker
方案B:逐个手动软重启(适合小流量场景,避免批量重启导致消费堆积)
先通过docker ps找到运行PHP-worker的容器ID,逐个发送SIGTERM信号即可:
docker kill --signal=SIGTERM <容器ID>
容器收到信号完成当前任务后会自动退出,Docker Swarm会自动拉起新的容器加载更新后的脚本。
注意事项
- 滚动更新的并行数不要设置过大,保证重启过程中有足够的worker在运行,避免Gearman任务堆积
- 停止宽限期必须大于你单个任务的最长执行时间,避免未处理完的任务被强制终止
- 若你的脚本没有挂载到宿主机,需要先构建新的镜像(包含更新后的PHP脚本),再执行
docker service update --image 新镜像名 PHP-worker,同样可以实现软重启效果
内容的提问来源于stack exchange,提问作者Guido Leibbrand
相关产品推荐
相关产品推荐

