在使用celery进行了一些“缺陷”场景之后(Redis是一个代理,不管它值多少),我们开始理解,在没有同时设置task_reject_on_worker_lost=true
的情况下设置acks_late=true
实际上是没有意义的,因为任务不会被重新调度(在我们的测试中也是如此)--任务永远停留在“未确认”类别中。
同时,每个人都说acks_late
将使任务在同一个/另一个工人身上重新调度,所以问题是:什么时候发生的?
官方文件显示
请注意,如果执行任务的子进程被终止(通过任务调用sys.exit()或通过信号),即使启用了acks_late,worker也会确认消息。
- 我们不希望重新运行强制内核向进程发送SIGSEGV(分段错误)或类似信号的任务。
- 我们假设系统管理员故意终止任务,不希望它自动重新启动。
- 分配过多内存的任务有触发内核OOM杀手的危险,同样的情况可能再次发生。
- 重新传递时总是失败的任务可能会导致高频率的消息循环,从而使系统停机。
如果您确实希望在这些场景中重新交付任务,则应该考虑启用task_reject_on_worker_lost设置。
有哪些不属于“工作人员被故意终止或由于捕获到信号”类别的“出错“示例?
2条答案
按热度按时间laawzig21#
重新启动、断电、硬件故障。注意,所有示例都假设预取乘数为1。
idfiyjo82#
请注意,celery 工作进程与实际执行任务的子进程之间存在差异。默认情况下,当您创建celery 工作进程时,它将创建一个“父”进程和x个执行任务的子进程,其中x是您拥有的CPU数量(您可以在文档中阅读更多信息,以及如何配置它)
我已经测试了所有不同的方案,以下是我的结论:
acks_late是关于当工作者死亡时会发生什么。task_reject_on_worker_lost是关于执行任务的实际进程。
例如,如果我有一个k8s pod运行celery 进程:如果我派Sigkill(冷关机)到pod,将acks_late设置为true将确保任务将由不同的工作进程接管。(例如,进入pod并杀死子进程,或者如果进程以某种方式自行退出),即使acks_late为true,也不会拾取任务。如果将task_reject_on_worker_lost设置为true,则会再次拾取任务。
希望这能澄清一切