Celery中设置acks_late=true却不开启task_reject_on_worker_lost的原因是什么
我们在使用Celery(消息代理为Redis)模拟多种“故障”场景后发现:如果不同时设置task_reject_on_worker_lost=true,单独配置acks_late=true几乎没有实际意义,测试中任务不会被重新调度,会一直停留在*unacked(未确认)*状态。
问题1:普遍认知中acks_late会让任务在同一个或其他工作节点上被重新调度,这种重调度场景会在什么时候触发?
官方文档说明如下:
请注意:即使开启了acks_late,若执行任务的子进程被终止(无论是任务调用sys.exit()退出,还是被信号终止),工作节点仍然会确认该消息。这一行为是有意设计的,原因如下:
- 我们不希望重新运行导致内核发送SIGSEGV(段错误)或同类信号的任务。
- 我们认为系统管理员主动终止任务时,不希望任务自动重启。
- 占用内存过高的任务可能触发内核OOM杀手,重新调度仍然会出现相同问题。
- 重新投递后始终失败的任务可能引发高频消息循环,拖垮整个系统。
如果你确实希望在上述场景下重新投递任务,可以考虑开启
task_reject_on_worker_lost配置项。
默认仅当Celery worker主进程完全失去向消息代理发送ACK确认信号的能力时,acks_late才会触发任务重调度,具体场景包括:
- worker所在服务器突然断电、硬件故障、系统内核崩溃导致整机宕机
- 对worker主进程执行
kill -9等无法被进程捕获的强制终止操作 - worker节点与Redis消息代理的网络完全断开,且持续时长超过消息代理的未确认消息超时阈值
- worker主进程陷入死锁、无限IO阻塞等异常状态,完全无法响应信号、执行回调逻辑
问题2:有哪些“异常场景”不属于“工作节点被主动终止或捕获信号终止”的范畴?
就是上述可触发acks_late默认重调度的所有场景:
- worker部署服务器硬件故障、突然断电、系统崩溃
- worker主进程被
kill -9等无法捕获的信号强制杀死 - worker与消息代理的网络长期断连,超出未确认消息超时阈值
- worker主进程陷入死锁、无限阻塞等无响应状态,无法执行任何信号处理逻辑
内容的提问来源于stack exchange,提问作者DimG
相关产品推荐
相关产品推荐

