了解芹菜任务预取

我刚刚发现了configuration选项CELERYD_PREFETCH_MULTIPLIER ( docs )。 默认是4,但(我相信)我想要预取或尽可能低。 我把它设置为1,这足够接近我正在寻找的东西,但还是有一些我不明白的东西:

  1. 为什么这个预取是一个好主意? 我真的不明白这个原因,除非消息队列和工作者之间有很多延迟(在我的情况下,他们当前运行在同一台主机上,最坏的情况是最终可能会在不同的主机上运行相同的数据中央)。 文件只提到缺点,但没有解释优点是什么。

  2. 许多人似乎把这个设置为0,期望能够以这种方式closures预取(我认为是合理的假设)。 但是,0意味着无限预取。 为什么有人会想要无限预取,不是完全消除了首先为任务队列引入的并发/asynchronous性?

  3. 为什么预取不能closures? 在大多数情况下,closures性能可能不是一个好主意,但是有没有技术上的原因使得这是不可能的? 还是只是没有实施?

  4. 有时候,这个选项连接到CELERY_ACKS_LATE 。 例如。 罗杰·胡(Roger Hu )通常写道: “用户真正想要的是让一个工人只保留subprocess的许多任务。 但是,如果没有启用迟到的承认,这是不可能的[…]»我不明白这两个选项是如何连接的,为什么没有另一个选项是不可能的。 另外提到的连接可以在这里find。 有人可以解释为什么这两个选项连接?

  1. 预取可以提高性能。 工人不需要等待经纪人的下一条消息来处理。 与经纪人沟通一次,处理大量的信息会带来性能上的提升。 与本地内存访问相比,从代理(甚至是本地代理)获取消息的成本很高。 工人也被允许分批承认信息

  2. 预取设置为零意味着“没有特定的限制”,而不是无限的

  3. 将预取设置为1被logging为等同于closures它,但情况可能并非总是如此(请参阅https://stackoverflow.com/a/33357180/71522

  4. 预取允许批量确认消息。 CELERY_ACKS_LATE = True在到达工作人员时阻止确认消息

只是一个警告:就像我使用redis broker + Celery 3.1.15进行testing一样,我读到的有关CELERYD_PREFETCH_MULTIPLIER = 1禁用预取的所有build议都是错误的。

为了certificate这一点:

  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 并不妨碍预取 ,它只是将预取限制为每个队列1个任务。

-Ofair , 不pipe文档说什么 , 也不妨碍预取

没有修改源代码,我还没有find任何完全禁用预取的方法。

老问题,但仍然加上我的答案,以防止他人帮助。 我的一些初步testing的理解与David Wolever的回答相同。 我只是在芹菜3.1.19testing了这个,而且-Ofair工作。 只是这并不意味着在工作节点级别禁用预取。 这将继续发生。 使用-Ofair在池员级别有不同的效果。 总之,要完全禁用预取,请执行此操作 –

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

添加更多的细节:

我发现工人节点将永远默认。 您只能通过使用CELERYD_PREFETCH_MULTIPLIER来控制预取的多less任务。 如果设置为1,则只会预取与节点中的池工作者(并发)数量一样多的任务。 所以如果你有concurrency = n,节点预取的最大任务将是n。

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

ACKS_LATE如何相关? ACKS_LATE = True意味着任务只有在任务成功时才会被确认。 如果没有,我想这是在工作人员接到时才会发生的。 在预取的情况下,该任务首先由工作人员接收(从日志确认),但将在稍后执行 。 我刚刚意识到,在rabbitmq的未确认消息中显示了优先消息。 所以我不确定是否将它设置为True是绝对需要的。 无论如何,我们的任务是由于其他原因而设置的(迟到)。

我不能评论David Wolever的答案,因为我的stackcred不够高。 所以,我已经把我的评论作为一个答案,因为我想分享我的经验与芹菜3.1.18和Mongodb经纪人。 我设法停止预取与以下内容:

  1. CELERYD_PREFETCH_MULTIPLIER = 1添加到芹菜configuration中
  2. CELERY_ACKS_LATE = True添加到芹菜configuration中
  3. 启动芹菜工人与选项: – --concurrency=1 -Ofair

将CELERY_ACKS_LATE保留为默认值,工作者仍然会预取。 就像OP一样,我没有完全掌握预取和迟到之间的联系。 我了解David所说的“CELERY_ACKS_LATE = True阻止在到达工作人员时收到确认消息”,但我不明白为什么迟到会与预取不兼容。 在理论上,预取仍然会允许延迟正确 – 即使在芹菜中没有这样编码?

Interesting Posts