Celery:没有设置task_reject_on_worker_lost=true而acks_late=true的原因是什么

Dim*_*imG 8 python redis celery

在使用 celery 处理了一些“缺陷”场景之后(Redis 是一个无论其价值如何的代理),我们开始了解到,如果acks_late=true没有同时设置,那么设置实际上是没有意义的,task_reject_on_worker_lost=true因为任务不会被重新安排(同样,在我们的测试)——任务永远保留在“未确认”类别中。

\n

与此同时,每个人都说这acks_late将使任务被重新安排在同一个/另一个工人身上,所以问题是:它什么时候发生?

\n

官方文档

\n
\n

请注意,如果执行任务的子进程被终止(通过任务调用 sys.exit() 或通过信号),即使启用了 acks_late,工作线程也会确认该消息。此\n行为是故意的,如\xe2\x80\xa6

\n
    \n
  • 我们不想重新运行强制内核向进程发送 SIGSEGV(分段错误)或类似信号的任务。

    \n
  • \n
  • 我们假设系统管理员故意杀死该任务不希望它自动重新启动。

    \n
  • \n
  • 分配过多内存的任务有触发内核 OOM 杀手的危险,同样的情况也可能再次发生。

    \n
  • \n
  • 重新交付时总是失败的任务可能会导致高频消息循环导致系统瘫痪。

    \n
  • \n
\n

如果您确实希望在这些情况下重新交付任务,您应该考虑启用 task_reject_on_worker_lost 设置。

\n
\n

有哪些可能的“出了问题”的示例不属于“工作人员故意终止或由于捕获信号而终止”类别?

\n

RNE*_*RNE 9

请注意,celery 工作进程与实际执行任务的子进程之间存在差异。默认情况下,当您创建 celery Worker 时,它将创建一个“父”进程和 x 个执行任务的子进程,其中 x 是您拥有的 CPU 数量(您可以在文档中阅读更多相关信息,并且如何配置)

我测试了所有不同的场景,以下是我的结论:

acks_late 是关于当工人死亡时会发生什么。task_reject_on_worker_lost 是关于执行任务的实际进程。

例如,如果我有一个运行 celery 进程的 k8s pod:如果我向 pod 发送 sigkill(冷关闭),则将 acks_late 设置为 true 将确保该任务将由不同的工作线程执行。但是,如果我以某种方式杀死执行任务的子进程(例如,进入 Pod 内部并杀死子进程,或者进程以某种方式自行退出),即使 acks_late 为 true,也不会拾取该任务。如果将task_reject_on_worker_lost设置为true,任务将被再次拾取。

希望能澄清一切


2ps*_*2ps 1

重启、断电、硬件故障。注意,所有示例均假设预取乘数为 1。