如何优雅地重启芹菜工人?

Posted

技术标签:

【中文标题】如何优雅地重启芹菜工人?【英文标题】:How do I restart celery workers gracefully? 【发布时间】:2012-04-03 15:04:24 【问题描述】:

在发布新版本以更新工作人员中的代码时,如何优雅地重新启动 celery 工作人员?

编辑: 我打算做的是这样的事情。

Worker 正在运行,可能正在向 S3 上传一个 100 MB 的文件 新版本来了 工人代码有变化 构建脚本向 Worker 发出信号 使用新代码启动新工作人员 在完成现有作业退出后收到信号的工人。

【问题讨论】:

【参考方案1】:

你应该看看 Celery 的autoreloading

【讨论】:

这似乎是实验性的This is an experimental feature intended for use in development only, using auto-reload in production is discouraged as the behavior of reloading a module in Python is undefined 还要注意,打开此标志会导致孤立进程运行,进而导致结果后端工作不正常 自动重载选项似乎已从 Celery 4 中删除【参考方案2】:

根据https://docs.celeryproject.org/en/master/userguide/workers.html#restarting-the-worker,你可以通过发送 HUP 信号来重启一个worker

 ps auxww | grep celeryd | grep -v "grep" | awk 'print $2' | xargs kill -HUP

【讨论】:

sudo ps auxww | grep celeryd | grep -v "grep" | awk 'print $2' | sudo xargs kill -HUP 排除 grep :-) 可以替换 grep celeryd | grep -v "grep" 与 grep [c]eleryd。只是说。 好像不是优雅重启吧?正如文档所说:“除了停止然后启动工人重新启动外,您还可以使用 HUP 信号重新启动工人,但请注意工人将负责重新启动自己,因此这很容易出现问题,不建议在生产中使用" 那么在生产环境中重新加载 Celery 以避免失败的最佳方法是什么? 对于 celery multi:“对于生产部署,您应该使用初始化脚本或其他过程监督系统”。至于 HUP:“这很容易出现问题,不建议在生产中使用 celery 文档在这个问题上似乎是自相矛盾的;这里它说不要在生产中使用celery multi,但在守护进程部分,示例systemd配置文件使用celery multi【参考方案3】:

长时间运行的任务会发生什么?我喜欢这样:长时间运行的任务应该完成他们的工作。不要打断他们,只有新任务才能获得新代码。

但目前这是不可能的:https://groups.google.com/d/msg/celery-users/uTalKMszT2Q/-MHleIY7WaIJ

【讨论】:

【参考方案4】:
celery multi start 1 -A proj -l info -c4 --pidfile=/var/run/celery/%n.pid
celery multi restart 1 --pidfile=/var/run/celery/%n.pid

http://docs.celeryproject.org/en/latest/userguide/workers.html#restarting-the-worker

【讨论】:

Uugh... 它在那里说“管理开发工作人员的最简单方法是使用 celery multi。对于生产部署,您应该正在使用 init 脚本或其他进程监督系统”。此答案不适用于在生产中运行! @webjunkie OP 没有说“在产品部署中”,所以不知道如果原始问题中没有提到它,你为什么要否决它。 他也没有说他想要一个解决方案,例如测试环境。很多人不会费心阅读更多内容,并且危险地使用他们认为正确的解决方案。因此,仅提及缺点是公平的,而不是简单地从文档中复制和粘贴某些内容而忽略注释并剥离进一步的建议。【参考方案5】:

我已经使用自动化脚本反复测试了 -HUP 解决方案,但发现大约 5% 的时间,工人在重新启动后停止接受新工作。

更可靠的解决方案是:

stop <celery_service>start <celery_service>

我现在已经使用了数百次,没有任何问题。

在 Python 中,您可以运行:

import subprocess
service_name = 'celery_service'
for command in ['stop', 'start']:
    subprocess.check_call(command + ' ' + service_name, shell=True)

【讨论】:

【参考方案6】:

如果您要走kill 路线,请 pgrep 进行救援:

kill -9 `pgrep -f celeryd`

请注意,这不是一项长期运行的任务,我不在乎它是否会残酷地终止。只是在开发期间重新加载新代码。如果它更敏感,我会走重启服务路线。

【讨论】:

(pkill 以更简洁的方式执行此操作) 不知道。但是,我仍然更喜欢查看将被预先杀死的进程列表:第 1 步 - 调整您的 pgrep,第 2 步通过将其提供给 kill 将其武器化。【参考方案7】:

你可以这样做:

celery multi restart w1 -A your_project -l info  # restart workers

Example

【讨论】:

【参考方案8】:

聚会可能会迟到。我用:

sudo systemctl stop celery

sudo systemctl start celery

sudo systemctl status celery

【讨论】:

Unit celery.service could not be found.

以上是关于如何优雅地重启芹菜工人?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不延迟任务的情况下优雅地重启 Celery

优雅重启 django-q qcluster

如何优雅地提高程序员的键盘使用效率?

失败时优雅地重启 Reactive-Kafka Consumer Stream

有没有办法非暴力地停止芹菜工人的特定任务?

再谈 Go Http 服务的优雅重启