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

Posted

技术标签:

【中文标题】有没有办法非暴力地停止芹菜工人的特定任务?【英文标题】:Is there any way to non-violently stop particular task of celery worker? 【发布时间】:2016-09-14 20:16:38 【问题描述】:

正如 Celery documentation 所说,已经执行的任务不会通过调用 .revoke() 中止,除非设置了 terminate=True。但不建议这样做,因为它会杀死工人本身,这可能已经开始了另一项任务。这是否意味着没有可靠、稳定的方法来做到这一点?

编辑:celery.contrib.abortable 不适合我,因为正如文档所述,它仅适用于数据库后端。

【问题讨论】:

这取决于您尝试终止的任务(网络、文件、数据库操作等),请看一下这个示例:***.com/questions/37039941/celery-python-revoke 在我的情况下,我的主要任务调用子进程除非我发送 SIGKILL 信号,否则不会终止。 Stopping celery task gracefully的可能重复 【参考方案1】:

一个正在运行的任务是worker的一个正在运行的子进程(当使用prefork时),这意味着中止一个任务的唯一方法是杀死正在运行它的子进程。

您可以尝试自己的撤销事件处理实现,试图找出子进程 ID 并只杀死那个,但老实说,不知道是否值得以及它是否真的可以工作。

我认为简短的回答是你不能。

无论如何有时需要杀死工人,特别是在项目的初始阶段,您仍然需要正确确定资源的尺寸,只需确保您在某处记录正在运行的任务,以便您可以重新安排它们或只使用CELERY_ACKS_LATE

【讨论】:

“无论如何杀死工人并不罕见” 什么通常条件会保证强制终止生产系统中的工人?我已经使用 Celery 几年了,唯一一次强制终止工人是在必须关闭站点进行维护时。 取决于用例,我以前在一个大型社区网站工作,我们在高峰期遇到了一些问题。工人们占用了大量的记忆和冻结。当然,这是因为我们没想到负载和工人的尺寸不正确。但我可以告诉你,一年内发生了几次,不考虑其他因素导致的机器完全崩溃。 我在 Louis 评论后通过回答澄清了。【参考方案2】:

您可以发送 HUP 信号而不是 TERM,它可以优雅地重新启动子进程而不会杀死工作人员。

In [80]: import signal

In [81]: x = add.delay(1, 2)

In [82]: x.revoke(terminate=True, signal=signal.SIGHUP)

【讨论】:

"除了先停止再启动worker重启,也可以使用HUP信号重启worker,但是注意worker会自己负责重启,这样容易出问题,不会推荐在生产中”Source @Louis 如果你有一个并发为 4 的 worker,它有 4 个进程一次运行 4 个任务。现在重新启动它只是撤销任务是一个坏主意,因为它可能会中断其他进程。上面的命令只会重启正在运行该任务的单个进程。

以上是关于有没有办法非暴力地停止芹菜工人的特定任务?的主要内容,如果未能解决你的问题,请参考以下文章

结束芹菜工人的任务、时间限制、工作阶段或客户的指示

如何停止芹菜工人进程

芹菜 - 中间的子任务失败后有没有办法继续执行链

芹菜工人和一个命令击败负载

芹菜工人的水平尺度导致相同的处理时间

如何在不同的机器上设置芹菜工人?