了解芹菜任务预取

时间:2013-04-16 14:42:31

标签: python celery celeryd

我刚刚发现配置选项CELERYD_PREFETCH_MULTIPLIERdocs)。默认值为4,但(我相信)我希望预取或尽可能低。我现在把它设置为1,这足够接近我正在寻找的东西,但还有一些我不理解的东西:

  1. 为什么这个预取是一个好主意?除非消息队列和工作人员之间存在大量延迟(在我的情况下,他们当前在同一主机上运行,​​最糟糕的情况可能最终在同一数据中的不同主机上运行),我真的没有理由看到它。中央)。文档仅提到了缺点,但未能解释其优点。

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

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

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

5 个答案:

答案 0 :(得分:23)

  1. 预取可以提高性能。工作人员无需等待代理处理的下一条消息。与代理进行一次通信并处理大量消息可以提高性能。与本地内存访问相比,从代理(甚至是本地代理)获取消息是昂贵的。工人也可以批量确认消息

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

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

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

答案 1 :(得分:20)

老问题,但仍然添加我的答案,以防它帮助某人。我从一些初步测试中得到的理解与David Wolever的回答相同。我刚刚在芹菜3.1.19中对此进行了测试,-Ofair确实有效。只是它并不意味着在工作节点级别禁用预取。这将继续发生。使用-Ofair具有不同的效果,即池工作者级别。总之,要完全禁用预取,请执行以下操作:

  1. 设置CELERYD_PREFETCH_MULTIPLIER = 1
  2. 在全局级别或任务级别设置CELERY_ACKS_LATE = True
  3. 启动工作时使用-Ofair
  4. 如果将并发设置为1,则不需要步骤3。如果你想要一个 更高的并发性,然后第3步对于避免任务获取至关重要 备份在一个可以运行长时间运行任务的节点中。
  5. 添加更多细节:

    我发现默认情况下工作节点总是预取。您只能使用CELERYD_PREFETCH_MULTIPLIER控制预取的任务数。如果设置为1,则它将仅预取与节点中池工作者数(并发)一样多的任务。因此,如果您有并发= n,则节点预取的最大任务将为n。

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

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

答案 2 :(得分:14)

只是一个警告:在我使用redis经纪人+ Celery 3.1.15进行测试时,我所读到的与CELERYD_PREFETCH_MULTIPLIER = 1禁用预取有关的所有建议都显然是错误的。

为了证明这一点:

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

  4. 开始5

  5. 请注意,Redis中的队列长度将立即从3降至CELERYD_PREFETCH_MULTIPLIER = 1
  6. -Ofair 不会阻止预取,它只是将预取限制为每个队列1个任务。

    SKSpriteNode *badguy = [SKSpriteNode spriteNodeWithTexture:[self.spriteAtlas textureNamed:@"test"]]; badguy.texture.filteringMode = SKTextureFilteringNearest; badguy.physicsBody.angularVelocity = 0; badguy.physicsBody.allowsRotation = NO; badguy.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(32, 32)]; despite what the documentation says也不会阻止预取

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

答案 3 :(得分:9)

我无法对David Wolever的答案发表评论,因为我的stackcred不够高。所以,由于我想与Celery 3.1.18和Mongodb经纪人分享我的经验,因此我将评论作为答案。我设法停止预取以下内容:

  1. Member [Measures].[Sales Daily Avg] AS Avg ( Descendants ( [Date].[Calendar].CURRENTMEMBER, [Date].[Calendar].[Date] ), CoalesceEmpty([Measures].[Total Sales] , 0) ) 添加到celery config
  2. SELECT { [Measures].[Sales Daily Avg], } ON COLUMNS, { [Date].[Calendar].[Calendar Year].Members } ON ROWS FROM [SalesCube] 添加到celery config
  3. 使用选项CELERYD_PREFETCH_MULTIPLIER = 1
  4. 启动芹菜工作者

    将CELERY_ACKS_LATE保留为默认值,工作人员仍然会预取。就像OP一样,我没有完全掌握预取和后期之间的联系。我理解大卫所说的" CELERY_ACKS_LATE = True会阻止在他们到达工作人员时确认消息,但我不明白为什么迟到的ack与预取不兼容。从理论上讲,预取仍然可以让你迟到 - 即使在芹菜中没有这样编码?

答案 4 :(得分:0)

我作为SQS经纪人经历了一些不同。

设置为:

CELERYD_PREFETCH_MULTIPLIER = 1
ACKS_ON_FAILURE_OR_TIMEOUT=False
CELERY_ACKS_LATE = True
CONCURRENCY=1

任务失败(引发异常)后,由于未确认消息(本地队列和远程队列),工作器不可用。

使工人继续消耗工作的解决方案是设置

CELERYD_PREFETCH_MULTIPLIER = 0

我只能推测在编写SQS传输时未考虑acks_late