了解芹菜任务预取
我刚刚发现了configuration选项CELERYD_PREFETCH_MULTIPLIER
( docs )。 默认是4,但(我相信)我想要预取或尽可能低。 我把它设置为1,这足够接近我正在寻找的东西,但还是有一些我不明白的东西:
-
为什么这个预取是一个好主意? 我真的不明白这个原因,除非消息队列和工作者之间有很多延迟(在我的情况下,他们当前运行在同一台主机上,最坏的情况是最终可能会在不同的主机上运行相同的数据中央)。 文件只提到缺点,但没有解释优点是什么。
-
许多人似乎把这个设置为0,期望能够以这种方式closures预取(我认为是合理的假设)。 但是,0意味着无限预取。 为什么有人会想要无限预取,不是完全消除了首先为任务队列引入的并发/asynchronous性?
-
为什么预取不能closures? 在大多数情况下,closures性能可能不是一个好主意,但是有没有技术上的原因使得这是不可能的? 还是只是没有实施?
-
有时候,这个选项连接到
CELERY_ACKS_LATE
。 例如。 罗杰·胡(Roger Hu )通常写道: “用户真正想要的是让一个工人只保留subprocess的许多任务。 但是,如果没有启用迟到的承认,这是不可能的[…]»我不明白这两个选项是如何连接的,为什么没有另一个选项是不可能的。 另外提到的连接可以在这里find。 有人可以解释为什么这两个选项连接?
-
预取可以提高性能。 工人不需要等待经纪人的下一条消息来处理。 与经纪人沟通一次,处理大量的信息会带来性能上的提升。 与本地内存访问相比,从代理(甚至是本地代理)获取消息的成本很高。 工人也被允许分批承认信息
-
预取设置为零意味着“没有特定的限制”,而不是无限的
-
将预取设置为1被logging为等同于closures它,但情况可能并非总是如此(请参阅https://stackoverflow.com/a/33357180/71522 )
-
预取允许批量确认消息。 CELERY_ACKS_LATE = True在到达工作人员时阻止确认消息
只是一个警告:就像我使用redis broker + Celery 3.1.15进行testing一样,我读到的有关CELERYD_PREFETCH_MULTIPLIER = 1
禁用预取的所有build议都是错误的。
为了certificate这一点:
- 设置
CELERYD_PREFETCH_MULTIPLIER = 1
- 排队5个任务,每个任务需要几秒钟(例如,
time.sleep(5)
) -
开始观察Redis中任务队列的长度:请
watch redis-cli -c llen default
-
启动
celery worker -c 1
- 请注意,Redis中的队列长度将立即从
5
降到3
CELERYD_PREFETCH_MULTIPLIER = 1
并不妨碍预取 ,它只是将预取限制为每个队列1个任务。
-Ofair
, 不pipe文档说什么 , 也不妨碍预取 。
没有修改源代码,我还没有find任何完全禁用预取的方法。
老问题,但仍然加上我的答案,以防止他人帮助。 我的一些初步testing的理解与David Wolever的回答相同。 我只是在芹菜3.1.19testing了这个,而且-Ofair工作。 只是这并不意味着在工作节点级别禁用预取。 这将继续发生。 使用-Ofair在池员级别有不同的效果。 总之,要完全禁用预取,请执行此操作 –
- 设置
CELERYD_PREFETCH_MULTIPLIER = 1
- 在全局级别或任务级别设置
CELERY_ACKS_LATE = True
- 在启动员工时使用
-Ofair
- 如果将并发性设置为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经纪人。 我设法停止预取与以下内容:
- 将
CELERYD_PREFETCH_MULTIPLIER = 1
添加到芹菜configuration中 - 将
CELERY_ACKS_LATE = True
添加到芹菜configuration中 - 启动芹菜工人与选项: –
--concurrency=1 -Ofair
将CELERY_ACKS_LATE保留为默认值,工作者仍然会预取。 就像OP一样,我没有完全掌握预取和迟到之间的联系。 我了解David所说的“CELERY_ACKS_LATE = True阻止在到达工作人员时收到确认消息”,但我不明白为什么迟到会与预取不兼容。 在理论上,预取仍然会允许延迟正确 – 即使在芹菜中没有这样编码?