受影响的版本:最新 (4.1.1)
preforked worker 忽略 sigterm 信号 - 只有负责热关机的父进程对其做出反应并优雅地关闭子进程。
当 preforked 工作进程获得 sigterm 时,它们会立即关闭(例如kill <pid>
):
celery_1 | [2018-06-04 09:19:57,376: ERROR/MainProcess] Process 'ForkPoolWorker-2' pid:26 exited with 'signal 15 (SIGTERM)'
当 sigterm 到达父工作进程时,将执行热关机。 如果同时预分叉的工人也收到了一个任期信号,任务就会被杀死。
我找不到在带有初始化系统的 docker 容器中正确关闭 celery 的方法。
(请参阅邮件列表:https://groups.google.com/forum/#!topic/celery-users/9UF_VyzRt8Q)。 看来我必须确保术语信号只到达父进程,而不是任何预分叉的工人。 当运行具有多个 celery 实例(例如 beat 和两个队列)的 bash 脚本时,这似乎非常困难
是否可以添加允许预分叉的工作进程忽略 sigterm 的功能?
为了在 Docker 容器内启动多个进程时有正确的信号传播,您可能需要一个进程管理器,例如supervisord 。
有关更多信息,这里是 docker 如何停止内容的概述: https: //www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/#docker -stop
此外,如果您已经在使用 docker,我建议您为每个容器解雇一名工人。
它更容易管理,容器没有那么多开销。 使用 k8s 等工具时也更容易进行自动缩放。
最后一件事。 如果您真的想推出自己的 bash 脚本来管理多个工作人员,则必须启动每个工作人员,然后无限期地休眠,直到出现 SIGTERM 为止。
当这种情况发生时,您可以去获取工人的 PID,然后优雅地停止每个人。
正如@georgepsarakis 所指出的,这基本上就是supervisord所做的。
感谢@georgepsarakis和@xirdneh提供有用的建议。 我设法通过 supervisord 获得了一个工作设置! 🎉
每个容器有一个工人也是一个很好的建议! 非常感谢!
最有用的评论
感谢@georgepsarakis和@xirdneh提供有用的建议。 我设法通过 supervisord 获得了一个工作设置! 🎉
每个容器有一个工人也是一个很好的建议! 非常感谢!