我使用基于 celery 存储库中示例的 supervisord 配置文件,并且在 celeryd 重新启动时遇到了一些问题:有时任务处理在重新启动 celery 后静默停止,而日志中没有任何错误消息。 进程在进程列表中仍然可见。
最后我发现,有时当进程重新启动时,celery 会产生额外的进程,而不是由 supervisord 管理,这会导致这些错误。 所以我开始在每次重启后仔细观察ps
输出,并通过 kill 手动杀死额外的进程
而今天我认为真正的原因找到了。 'stopwaitsecs' 选项的默认 supervisord 值为 10 秒。 这意味着 10 秒后 celery 进程将被 KILL 信号而不是 TERM 杀死。 在这种情况下,芹菜似乎不喜欢被杀死并尝试产生额外的进程。
所以我认为最好在所有supervisord示例配置文件中添加'stopwaitsecs = 600'之类的东西(来自faq:“你永远不应该用KILL信号(-9)停止celeryd,除非你已经尝试了TERM一些次并等待几分钟让它有机会关闭。”)并调查 KILL 信号上的 celeryd 行为:文档中提到任务将丢失(在许多情况下这是可以容忍的)但产生的问题过程有点奇怪。
收到KILL
信号时产生的进程确实很奇怪。 在supervisord
之外使用时我看不到这种行为,所以也许这是由它引起的?
如果你安装了setproctitle
模块,celery 应该在ps
列表中报告进程的类型,你能这样做来调查创建了什么样的进程吗?
( easy_install setproctitle
)
将超时设置为600
可能很好。 是否有任何无限设置(如果需要太长时间可能会发出警告)? 当celeryd
被TERM
(这是首选的关闭信号)杀死时,它会停止接收消息并等待当前正在执行的任务完成。 而且我猜对于大多数应用程序来说,中途终止是不可接受的。
至于进程生成:setproctitle 和监视进程 ID 很有帮助。 它不是进程生成。 当父进程被杀死时,工作进程保持活动状态。
这是一个手动杀死和零超时的supervisord重启模拟:
4976 ? Ss 0:00 /usr/bin/python /usr/bin/supervisord --pidfile /var/run/supervisord.pid
5422 ? S 0:01 \_ [celerybeat] --schedule=/var/lib/celery/celerybeat-schedule-nadovmeste --loglevel=INFO
6101 ? Sl 0:00 \_ [celeryd.MainProcess] Running... (--loglevel=INFO)
6108 ? S 0:00 \_ [celeryd.PoolWorker-1]
nadovmeste:~# kill 6101 & kill -9 6101 &
ps -afx:
4976 ? Ss 0:00 /usr/bin/python /usr/bin/supervisord --pidfile /var/run/supervisord.pid
5422 ? S 0:01 \_ [celerybeat] --schedule=/var/lib/celery/celerybeat-schedule-nadovmeste --loglevel=INFO
6867 ? Sl 0:00 \_ [celeryd.MainProcess] Running... (--loglevel=INFO)
6875 ? S 0:00 \_ [celeryd.PoolWorker-1]
6108 ? S 0:00 [celeryd.PoolWorker-1]
我只能通过kill
和kill -9
之间的这种人工竞赛来重现这一点。 有时工人会被正确杀死。 这个问题似乎是特定于主管的,因为当我从控制台启动 celeryd 时,我没有运气重现它。
经过几次尝试后,我能够使用控制台启动的脚本重现这一点:
/home/nadovmeste/envs/nadovmeste/bin/python /home/nadovmeste/src/nadovmeste/manage.py celeryd -B --loglevel=INFO&
然后在另一个终端会话中:
nadovmeste:~# ps -afx
6450 ? Ss 0:00 \_ sshd: root@pts/2
6452 pts/2 Ss+ 0:00 \_ -bash
9343 pts/2 Sl 0:00 \_ [celeryd.MainProcess] Running... (-B --loglevel=INFO)
9350 pts/2 S 0:00 \_ [celeryd.PoolWorker-2]
9355 pts/2 S 0:00 \_ [celerybeat]
nadovmeste:~# kill 9343 & kill -9 9343
nadovmeste:~# ps -afx
4526 ? Ss 0:00 \_ sshd: root@pts/1
4529 pts/1 Ss 0:00 | \_ -bash
9366 pts/1 R+ 0:00 | \_ ps -afx
6450 ? Ss 0:00 \_ sshd: root@pts/2
6452 pts/2 Ss+ 0:00 \_ -bash
...
9350 pts/2 S 0:00 [celeryd.PoolWorker-2]
9355 pts/2 S 0:00 [celerybeat]
在 supervisord 文档中没有找到任何用于无限超时的特殊选项并带有警告。 如果这是我们想要的,可能非常大的数字就足够了。
也许这与 celerybeat 有关,因为我只有在使用-B
选项后才能重现控制台启动的 celeryd 的问题。
如果我在本地测试一些 celery 任务并且我使用 -B 选项,有时当我使用 ctrl-c 时该进程不会被终止。
我无法在本地复制此内容。 顺便说一句,你在运行主分支吗? 我刚刚修复了一个可能导致关机的错误。 如果您可以对此进行测试,那就太好了。
是的,我正在运行最新的 master 分支。 我看到你的错误修复提交并希望它会有所帮助,但它似乎对我的情况没有帮助:最新的芹菜似乎表现相同。 但是最初的问题有可能已经解决了——我只通过立即杀死来检查这个问题。 我现在无法绕过它 :) 我的设置无法重现 ctrl-c 问题。
所以错误报告,简化:http: //gist.github.com/401028 。 结果总是相同的(有时不是)。 我有一些周期性任务和一些非周期性任务。 任务很简单,不需要太多时间来完成。 杀死主进程后子进程仍然活着是一个错误吗? 如果是这样并且您无法复制它,那么我将尝试提供最小的项目。
celerybeat 杀死行为很有趣:当我杀死 hang(?) celerybeat 进程时,hanging(?) 工作进程也会关闭。
@kmike我仍然无法使用上面的命令进行复制。 也许是因为我在 OS X 上,或者你正在运行 Python 2.5? (我正在运行 2.6.1)
可以用--loglevel=DEBUG?
运行它它可以提供一些关于它在哪里停止的信息。
celerybeat 进程是由主进程启动的,所以我假设主进程正在等待
celerybeat 在杀死剩余的池进程之前退出。
我以为主进程被杀死了:它在进程列表中不可见。 虽然没有太多的流程管理经验。
我的设置是 Debian Lenny + python 2.5。
我将尝试使用 --loglevel=DEBUG 运行 celeryd 并在我的 macbook 上重现它。
嗯,你当然是对的。 这几乎就像节拍进程获得了池进程的所有权。
我只是尝试使用 python 2.5 在 Debian Lenny 上重现,它就在那里工作。
尝试用 TERM 和 INT 杀死。
求教,谢谢帮助。
我认为最初的问题是通过增加 supervisord 超时和您的错误修复提交来解决的。 模拟不正确,因为我使用kill -9
命令并且它们发送 KILL 信号而不是 TERM。 随着 TERM 信号进程被正确杀死。
Supervisord 使用 TERM 信号,所以一切都应该没问题。
但让我有点害怕的是最初的错误没有被调查。 我会尝试复制它并让你知道。
啊! 我很抱歉。 我没有仔细阅读这个问题。 是的! 这正是你用 SIGKILL 杀死它时发生的情况。 无法捕捉到 9 信号,因此我们对此 AFAIK 无能为力。
如果您在终止 Celery 工人时仍然遇到问题,您可以尝试在增加stopwaitsecs
stopasgroup=true
#$ 。
最有用的评论
如果您在终止 Celery 工人时仍然遇到问题,您可以尝试在增加
stopwaitsecs
stopasgroup=true
#$ 。