Celery: 重启 celery 问题和更好的 supervisord 配置文件

创建于 2010-05-09  ·  16评论  ·  资料来源: celery/celery

我使用基于 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 行为:文档中提到任务将丢失(在许多情况下这是可以容忍的)但产生的问题过程有点奇怪。

最有用的评论

如果您在终止 Celery 工人时仍然遇到问题,您可以尝试在增加stopwaitsecs stopasgroup=true #$ 。

所有16条评论

收到KILL信号时产生的进程确实很奇怪。 在supervisord之外使用时我看不到这种行为,所以也许这是由它引起的?

如果你安装了setproctitle模块,celery 应该在ps列表中报告进程的类型,你能这样做来调查创建了什么样的进程吗?

( easy_install setproctitle )

将超时设置为600可能很好。 是否有任何无限设置(如果需要太长时间可能会发出警告)? 当celerydTERM (这是首选的关闭信号)杀死时,它会停止接收消息并等待当前正在执行的任务完成。 而且我猜对于大多数应用程序来说,中途终止是不可接受的。

至于进程生成: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]       

我只能通过killkill -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 #$ 。

此页面是否有帮助?
0 / 5 - 0 等级