RabbitMQ(Java)多个消费者性能问题

时间:2018-04-16 14:55:13

标签: java mongodb rabbitmq amqp mongodb-java

我正在实现从MongoDB获取数据的日常工作(大约300K文档),并且每个工作都在RabbitMQ队列上发布消息。 另一方面,我有一些消费者在同一个队列中,理想情况下应该并行工作。

一切正常,但没有我想象的那么多,特别是关于消费者的表现。

这是我声明队列的方式:

rabbitMQ.getChannel().queueDeclare(QUEUE_NAME, true, false, false, null);

这就是发布的方式:

rabbitMQ.getChannel().basicPublish("", QUEUE_NAME, null, body.getBytes());

因此,用于声明队列的通道用于发布所有消息。

这就是消费者在for循环中实例化的方式(总共10个,但可以是任意数字):

Channel channel = rabbitMQ.getConnection().createChannel();
MyConsumer consumer = new MyConsumer(customMapper, channel, subscriptionUpdater);
channel.basicQos(1);    // also tried with 0, 10, 100, ...
channel.basicConsume(QUEUE_NAME, false, consumer);

因此,对于每个消费者,我创建了一个新频道,这由日志确认:

...
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@bdd2027
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@5d1b9c3d
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@49a26d19
...

据我所熟悉的RabbitMQ经验,这应该保证所有消费者都被召唤。 顺便说一下,消费者需要0.5到1.2秒才能完成任务。我刚发现很少3秒钟。

我有两个独立的队列,我重复上面所说的两次(使用相同的RabbitMQ连接)。

因此,我测试了为每个队列发布100条消息。他们两个都有10个消费者,qos = 1。

我没想到的确有一个10 / s的交付/消费性能,而是我注意到了:

  • 实际值约为0.4和1.0。
  • 至少所有绑定到队列的消费者都收到了一条消息,但它看起来不像“公平调度”。
  • 消耗两个队列中的所有消息大约需要3分30秒。

enter image description here enter image description here

我是否错过了RabbitMQ中线程的主要概念?或者任何可能仍处于默认值的特定配置? 我很少见,所以这可能是可能的。

请注意,我处于幸运的位置,我可以控制出版和消费部分:)

我在本地使用RabbitMQ 3.7.3,因此它不会出现任何网络延迟问题。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

RabbitMQ频道和消费者的设置最终是正确的:每个消费者都有一个频道。

问题在于消费者调用同步方法来查找和更新MongoDB文档。

这延迟了一些消费者的执行时间:即使最糟糕的是,我添加的消费者越多(想加快处理速度),我获得的消息率就越低。

我已将MongoDB部分移到了发布方面,我不必关心同步,因为它只是由一个发布者按顺序完成的。我的交付率略有下降,但现在只有5名消费者,我很容易达到50-60 / s的确认率。

经验教训:

  • 为发布商创建单独的频道。
  • 为每位消费者创建一个单独的渠道。
  • 让RabbitMQ管理消费者的线程( - >你可以在主线程上实例化它们。)
  • (如果可能的话)退出发布,让队列有100%的时间与消费者打交道。
  • 设置qos>每个消费者渠道1个。但这实际上取决于您的场景和架构:您必须进行一些性能测试。

作为一般规则:

  • (1)计算/估计交货时间。
  • (2)计算/估计确认时间。
  • (3)计算/估计消费者时间。
  • qos =(1)+(2)+(3)/(3)

这将为您提供初始qos值,以根据您的方案进行测试和调整。最终目标是为所有可用的消费者提供100%的利用率。