当发布者提供有序消息时,消费者的水平扩展

时间:2018-02-14 16:02:53

标签: asynchronous rabbitmq microservices

在面向分布式服务的体系结构中,假设我有一个使用RMQ向消费者发送消息的生产者。

然后我们决定通过增加更多消费者来横向扩展我们架构的消费部分,并且我们遇到了一些限制。

发布者在其发送的每封邮件中提供序列号。消费者根据消息的序列号处理消息非常重要。

每次处理给定资源时,让我们说A,发布者将发送RMQ消息,说明"嘿,让我们为A"然后"嘿,让我们为A"做序列2等等。

例如,如果发布者为A提供3条消息,其中包含序列1,2和3,则3条消息将分发给我们的消费者的3个不同实例。序列2的消息被重新排队,直到序列1处理得很好,序列3也是如此。

最后,消息都处理得很好,但经过多次重试!这会导致我们的系统出现一些延迟,因为如果我们要消耗100个序列,我们会重试多次。

一种可能的解决方案是确保给定资源的每组序列必须由同一个消费者处理。但是我们怎样才能实现呢?

我如何避免重新排队,以确保我们的消费者的每个实例始终获得订购资源的消息?

3 个答案:

答案 0 :(得分:2)

尝试以下方法:

  • 创建topic exchange
  • 让您的制作人向其发送消息 每个资源的主题:资源A的主题A,主题B 资源B等等。
  • 让1位消费者听一个主题。每个都使用持久队列 消费者,因此队列将在消费者重启后继续存在。如果你有 生产者 - >一次交换 - > 1个队列 - > 1消费者消息路径, 邮件的顺序是有保证的,请参阅RabbitMQ broker semantics 详情。
  • 让您的消费者只有在获得1 message at a timeack时才能获得 处理完成。

这有望为您提供所需的顺序处理,而且您不需要重新排队消息。

请注意,如果您的消费者在完成处理任务和acking消息之间死亡,则可能会两次收到相同的消息。

答案 1 :(得分:0)

我不熟悉RMQ,但我会尽力帮助。

对我而言,您似乎希望以每个消费者专用于单一资源的方式扩展您的消费者。这是必要的,因为您在单个资源的序列之间存在依赖关系,因此没有必要在多个使用者之间分配工作。

我有Kafka的经验,你可以使用所谓的"主题"发送消息给消费者专门用于从那里抓取工作项的单个主题。

不确定这是否可以在RMQ上使用。

如果这不是您架构上的选项,请尝试以下操作: 通过首先检查消息有效负载是否与该资源相关来为资源专用一个消费者。如果是,则执行工作,如果没有则重新排队。

答案 2 :(得分:0)

RabbitMQ只是一个路由消息的代理。您不应该使用它来管理您的业务,因为您将拥有许多复杂的路由规则。

我个人用一个消费者解决了这个问题。它的目标是侦听队列,根据业务规则在堆栈中推送事件。如果您仍然需要扩展消费者数量,则可以使用反应式体系结构模式,这样您就可以协调所有分叉实例之间的负载平衡。

使用RabbitMQ的另一个解决方案是设置消息的优先级并创建消费者监听特定优先级。 https://www.rabbitmq.com/priority.html

如果这两个解决方案仍无法解决您的问题,您可以按消费者设置队列,并在重新排队消息时将序列发送到相应的队列中。使用这个简单的解决方案,您将始终确保同一消费者读取给定的消息,但您将失去负载平衡的好处。