具有多个线程的多个消费者的RabbitMQ负载平衡

时间:2015-01-28 00:59:38

标签: java multithreading spring rabbitmq

我是RabbitMQ的新手,我的任务是修复正在发生的负载平衡错误。

以下是设置: 我们使用RabbitMQ在RPC Api上运行Protobuf。

对api的请求将发布到Rabbit,然后由3个实例之一使用(API分布在3个应用程序实例中)。

每个实例都设置为使用10个线程来处理请求并返回响应。我们通过设置一个带有10个ConcurrentConsumers的SimpleMessageListener来实现这一点,这导致10个相应的线程处理每个消息。

这导致:

Instance 1: Consumers 1-10, Instance 2: Consumers 11-20, Instance 3: Consumers 21-30. 

由于Rabbit使用循环方法在消费者之间分配负载(相对于应用程序实例分配负载)如果有5条消息通过,我们最终会看到这样的负载:

Instance 1: Threads 1-5 in use (6-10 idle), Instance 2: Idle, Instance 3: idle. 

我想要发生的事情是: 5条消息:

Instance 1: Threads 1,2 in use, Instance 2: threads 1,2 in use Instance 3: Thread 1 in use. 

换句话说,我想根据实例循环(例如实例1(消费者1),2(11),3(21),1(2),2(12))而不是消费者(例如,实例1,消费者1-5)。

使用Spring AMQP(1.2.1)和Spring Rabbit(1.2.1)库是否可以实现?我的第一个想法是将每个实例的并发使用者减少到1(因此兔子均匀地分配给应用程序的每个实例),然后使用执行程序为每个请求启动一个线程(每个实例最多10个线程)。

我还没有看到其他人遇到类似的问题,所以我希望有人可以给我一些指导!我主要试图看看我是否可以对我们当前的设置进行配置更改,或者我是否需要手动实现某些功能。

谢谢!

2 个答案:

答案 0 :(得分:2)

如果您想循环到三台服务器,那么我认为您的想法(并发消费者= 1)是最佳选择。

您应该注意,它只是与应用程序连接以侦听消息的顺序一样公平,例如:

  1. app1侦听
  2. app2侦听
  3. 消息已分派到app1
  4. app1侦听
  5. app3听
  6. 消息已发送至app2
  7. 消息已发送至app1 ***此处不是循环播放
  8. 消息已发送至app3
  9. 如果您的邮件中没有某种定位信息,那么您的最大努力将与您的流程连接以接收邮件一样有序。

    但是,如果你的消费者数量为1并将消息传递给执行者并立即收听更多消息,我会打赌你会得到一个非常均匀的分发。

    我还应该注意,您将在此设置中更难以使ACK / NACK变得更难。如果您正在使用Java 8,那么CompletableFuture API可以很好地适用于从传递的线程中做一些直接的ACK / NACK

答案 1 :(得分:0)

您可以使用 consumer priorization 实现此行为。只需为每个实例的每个消费者提供 1-10 的优先级。由于文档,这应该平均分配工作负载。