0

我有一个 RabbitMQ 设置,其中作业被发送到交换器,交换器将它们传递到队列。消费者依次正确执行队列中的作业。然而,这些工作是漫长的过程(至少几分钟)。为了可扩展性,我需要能够让多个消费者从队列顶部选择一个作业并执行它。

消费者正在一个名为“队列”的 Heroku 测功机上运行。当我缩放测功机时,它似乎为每个测功机创建了额外的消费者(我可以在 RabbitMQ 仪表板上看到这些)。然而,队列中的任务数量没有改变——额外的消费者似乎什么都不做。请查看下图以了解我的设置。

RabbitMQ 设置

我在这里错过了什么吗?

  1. 为什么消费者显示为“空闲”?我从我的日志中知道,至少有一个消费者正在积极地完成一项任务。
  2. 当至少有一个消费者肯定在努力工作时,我的消费者利用率怎么可能是 0%。
  3. 我怎样才能让其他三个消费者真正从队列中拉出一些工作?

谢谢

编辑:我发现循环调度实际上是有效的,但前提是当消息发送到队列时其他消费者已经在运行。这对我来说似乎是违反直觉的行为。如果我看到一个很大的队列并想添加更多的消费者,那么添加的消费者不会做任何事情,直到更多的项目被添加到队列中。

4

2 回答 2

1

为了从另一个答案中找出关键点,这里可能的罪魁祸首是pre-fetching,如“Consumer Acknowledgments and Publisher Confirms”中所述。

服务器不会一次发送一条消息并等待它被确认,而是将批量发送给消费者。如果消费者确认了一些但随后崩溃,则剩余的消息将发送给不同的消费者;但如果消费者仍在运行,则未确认的消息将不会发送给任何新的消费者。

这解释了您所看到的行为:

  1. 您创建队列,并向其传递一些消息,而没有运行消费者。
  2. 您运行一个消费者,它会预取队列中的所有消息
  3. 你运行第二个消费者;尽管队列不为空,但所有消息都被标记为发送给第一个消费者,等待确认;所以第二个消费者处于空闲状态。
  4. 一条新消息到达队列;它以循环方式分发给第二个消费者。

解决方案是在消费者中指定basic.qos选项。如果将此设置为 1,则 RabbitMQ 在确认前一条消息之前不会向消费者发送消息;具有该设置的多个消费者将以严格的循环方式接收消息。

于 2020-01-22T14:50:11.540 回答
1

我对 Heroku 不熟悉,所以我不知道 Heroku worker 是如何构建 rabbitMQ 消费者的,我只是快速浏览了 Heroku 文档。

为什么消费者显示为“空闲”?

我认为您的意思是队列“空闲”?因为队列state是关于队列的流量的,它只是意味着队列的工作线程没有在做的工作。当消息在队列中发布时,它将变为“运行”。

当至少有一个消费者肯定在努力工作时,我的消费者利用率怎么可能是 0%。

和队列状态一样,从官方的解释来看,consumer utilisation太低的意思是:

  • 有更多的消费者
  • 消费者更快
  • 消费者的预取计数更高

在您的情况下,prefetch_count = 0意味着对预取没有限制,所以它太大了。并且Messages.total = Messages.unacked = 78意味着您的消费者太慢了,消费者已经处理了两条多条消息。

所以如果你的消息率不够大,队列的stateand字段就没用了。consumer utilisation

如果我看到一个很大的队列并想添加更多的消费者,那么添加的消费者不会做任何事情,直到更多的项目被添加到队列中。

因为这些未确认的消息已经被现有消费者预取,所以除非您requeue收到未确认的消息,否则它们不会被新消费者消费。

于 2020-01-12T10:24:42.533 回答