RabbitMQ 将消息不均匀地分配给消费者

Posted

技术标签:

【中文标题】RabbitMQ 将消息不均匀地分配给消费者【英文标题】:RabbitMQ distributing messages unevenly to consumers 【发布时间】:2016-10-09 18:33:19 【问题描述】:

我们发现消息队列的使用者从字母范围顶部的队列中提取消息的问题。我们有两个应用程序:producersubscriber。我们正在使用 RabbitMQ 3.6.1

假设消息队列是这样设置的:

我们的第一个应用程序 producer 将每秒 100 条消息放入每个队列:

我们的第二个应用程序,subscriber,有五个独特的消费者方法,可以处理每个队列上的消息。每个方法都绑定到它各自的队列。 订阅者 的预取值为 1,这意味着它一次只能保存一条消息,而与队列无关。我们可以像这样运行许多 subscriber 实例:

所以情况是这样的:每个队列每秒接收 100 条消息,我们有四个订阅者实例在消费这些消息,所以每个队列有四个消费者。假设每个消费者方法可以处理 25 msg/sec。

发生的情况是,不是所有队列都被平等地消耗,而是按字母顺序排列较高的队列获得优先级。似乎当 subscriber 准备就绪时,RabbitMQ 会查看此特定就绪通道绑定到的队列列表,并选择第一个带有待处理消息的队列。

在我们的情况下,A_QUEUE 将消耗所有消息。 B_QUEUE 在某些竞态条件下可能会有一些消耗,但 C_QUEUE/D_QUEUE 尤其是 E_QUEUE 很少会被触及。

如果我们关闭 publisher,队列最终会从上到下耗尽。

是否可以配置 RabbitMQ 本身,甚至可能配置通道以使用某种循环分配策略,甚至可能是随机策略,这样当通道有大量绑定队列时,都是消息未决,分配是否均匀?

【问题讨论】:

【参考方案1】:

澄清一下:您有一个包含多个消费者的单个订阅者应用程序,对吧?

我猜你在订阅者应用程序中使用单个 RabbitMQ 连接。

您是否还为所有消费者重复使用单个 RabbitMQ 通道?如果是这样,那将是一个问题。确保为您启动的每个消费者使用一个新频道。

【讨论】:

我们只希望每个订阅者应用程序有一个线程,这意味着单个通道上有多个消费者,因为预取是每个通道的。 详细说明:每个应用程序都是单线程的,我们只希望一次处理一条消息。因此,预取为 1 的单个通道可以解决此问题。 “单个渠道上的多个消费者” - 那么我认为您不会解决您遇到的问题 我也是这么想的。直到最近,这还不是问题。无论如何,谢谢,感谢您的回复。【参考方案2】:

也许图片是错误的,但如果不是,那么你的设置是错误的。如果您要让订阅者监听每个队列,则不需要 4 个队列。您只需要一个队列,该队列有多个使用同一订阅者的实例。

现在回答,可以(但不需要配置,只要prefetch为1),其实rabbitmq确实是平均分配消息的。您可以找到关于 here 的信息,并且在同一个地方实际上您的设置应该是什么样子。这是链接中的引述。

RabbitMQ 只是在消息进入队列时调度消息。 它不查看未确认消息的数量 消费者。它只是盲目地将第 n 个消息发送到第 n 个 消费者。

【讨论】:

除非交易所正在复制消息(使用扇出),因为他希望每条消息至少被处理 5 次,是的,我认为他的事情过于复杂了。 感谢您的反馈。当我们设计系统时,我们有两个选择:每个类型的队列,它为我们提供度量和细粒度控制,或者我们封装对象的一个​​大队列。我们最后选择了前者。我不认为 RMQ 分布不均匀,只是预取一个,“下一条消息”总是在顶部队列中。 你可以为每个类型做队列,这很好,甚至更好,但在这种情况下你还需要有一个“每个类型的订阅者”。 RMQ 队列是 FIFO。并且分发遵循“先到先得”的原则,所以第一个连接的订阅者会得到第一个消息等......如果问题得到回答,我会很感激反馈?这是关于配置循环分发的,但我可能错过了什么? 我完全明白 RMQ 队列是 FIFO,但如果你举一个更简单的例子:四个队列,每个队列有 100 条消息。获取一个具有一个通道但有四个绑定的订阅者,每个队列一个,并预取 1。订阅者将在移动到另一个队列之前分别通过第一个队列的前 100 条消息。为什么是“第一”队列?因为它的字母顺序更高?有没有办法随机化而不是选择按字母顺序排列的最高队列?这就是问题所在,我认为它本身没有答案。 只是指出,实际的实现比这复杂得多,但这是我将其归结为的简单版本。所以它可能会让你想“哦,为什么要那样做”,但我们之所以这样设置它是有原因的,我们只需要一个更均匀的分布,而不是数组中的第一个队列有待处理的消息。

以上是关于RabbitMQ 将消息不均匀地分配给消费者的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 消费预取数量的优化

Kafka数据消费

rabbitmq 消息类型

RABBITMQ初探——消息分发

RabbitMQ公平队列原理实现

RabbitMQ 消息确认与公平调度消费者