了解芹菜任务预取

2024-05-23 17:49:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚刚发现了配置选项CELERYD_PREFETCH_MULTIPLIERdocs)。默认值是4,但(我相信)我希望预取关闭或尽可能低。我现在把它设为1,这已经足够接近我要找的了,但是仍然有一些事情我不明白:

  1. 为什么这个预取是个好主意?我真的看不出其中的原因,除非消息队列和工作线程之间有很多延迟(在我的例子中,它们当前运行在同一个主机上,最坏的情况下可能最终运行在同一个数据中心的不同主机上)。文档只提到了缺点,但没有解释优点是什么。

  2. 许多人似乎将此设置为0,希望能够以这种方式关闭预取(我认为这是一个合理的假设)。但是,0表示无限制预取。为什么会有人想要无限制的预取,这不是完全消除了您最初引入任务队列的并发性/异步性吗?

  3. 为什么不能关闭预取?对于性能来说,在大多数情况下关闭它可能不是一个好主意,但是这不可能是有技术原因的吗?或者只是没有实施?

  4. 有时,此选项连接到CELERY_ACKS_LATE。例如。Roger Hu writes~[…]通常[用户]真正想要的是让一个工作进程只保留与子进程一样多的任务。但是,如果不启用延迟确认,这是不可能的[…];我不明白这两个选项是如何连接的,以及为什么一个选项没有另一个选项是不可能的。有关连接的另一个说明可以找到here。有人能解释一下为什么这两个选项是联系在一起的吗?


Tags: 消息docs队列进程选项情况原因事情
3条回答
  1. 预取可以提高性能。工人不需要等待代理处理下一条消息。与代理通信一次并处理大量消息可以提高性能。与本地内存访问相比,从代理(甚至从本地代理)获取消息是昂贵的。工人也可以分批确认消息

  2. 预取设置为零表示“无特定限制”,而不是无限制

  3. 将prefetching设置为1相当于将其关闭,但情况并非总是如此(请参见https://stackoverflow.com/a/33357180/71522

  4. 预取允许批量确认消息。芹菜ACKS_LATE=True防止在联系员工时确认消息

只是一个警告:在我使用redis broker+celeric3.1.15进行测试时,我所读到的关于禁用预取的所有建议都明显是错误的。

为了证明这一点:

  1. 设置CELERYD_PREFETCH_MULTIPLIER = 1
  2. 排队5个任务,每个任务需要几秒钟(例如,time.sleep(5)
  3. 开始监视Redis中任务队列的长度:watch redis-cli -c llen default

  4. 开始celery worker -c 1

  5. 注意,Redis中的队列长度将立即从5减少到3

CELERYD_PREFETCH_MULTIPLIER = 1并不阻止预取,它只是将预取限制为每个队列一个任务。

-Ofairdespite what the documentation says,也不阻止预取

除了修改源代码之外,我还没有找到完全禁用预取的方法。

老问题了,但还是加上我的答案,以防对别人有帮助。我从最初的测试中得到的理解和大卫·沃尔夫的答案是一样的。我刚刚在芹菜3.1.19中做了更多的测试,-Ofair确实有效。只是它并不意味着要在工作节点级别禁用预取。这将继续发生。使用-Ofair在池工作线程级别有不同的效果。总之,要完全禁用预取,请执行以下操作:

  1. 设置CELERYD_PREFETCH_MULTIPLIER = 1
  2. 在全局级别或任务级别设置CELERY_ACKS_LATE = True
  3. 启动工作进程时使用-Ofair
  4. 如果将concurrency设置为1,则不需要执行步骤3。如果你想 更高的并发性,那么步骤3对于避免任务获得 备份在可以运行长时间运行任务的节点中。

添加更多详细信息:

我发现默认情况下工作节点将始终预取。您只能通过使用CELERYD_PREFETCH_MULTIPLIER来控制它预取的任务数。如果设置为1,它将只预取与节点中池工作线程(并发)数量相同的任务。因此,如果concurrency=n,则节点预取的最大任务数将为n

如果没有-Ofair选项,对我来说,如果池工作进程之一正在执行长时间运行的任务,则节点中的其他工作进程也将停止处理节点已预取的任务。通过使用-Ofair,这就改变了。即使节点中的某个工作进程正在执行长时间运行的任务,其他工作进程也不会停止处理,而是继续处理节点预取的任务。所以我看到了两个级别的预取。一个在工作节点级别。另一个在个体工人层面。对我使用-Ofair似乎在工作级禁用了它。

如何与ACKS_LATE相关?ACKS_LATE = True表示只有当任务成功时才会确认该任务。如果没有,我想当工人收到它的时候就会发生。在预取的情况下,该任务首先由工作进程接收(从日志中确认),但稍后将执行。我刚刚意识到,在rabbitmq中,预取的消息显示在“未确认的消息”下。所以我不确定是否绝对需要将其设置为True。因为其他原因,我们的任务被设置成那样(延迟确认)。

相关问题 更多 >