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

RabbitMQ (Java) multiple consumers performance issue

我正在执行一项日常工作,该工作从 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.

我没想到会有 delivery/consume 10/s 的性能,相反我注意到:

我是否遗漏了 RabbitMQ 中线程的主要概念?或者任何可能仍处于默认值的特定配置? 我才几天就开始使用它,所以这可能是可能的。

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

我在本地使用 RabbitMQ 3.7.3,所以这不可能是任何网络延迟问题。

感谢您的帮助!

RabbitMQ 通道和消费者的设置最终是正确的:因此每个消费者一个通道。

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

这会延迟一些消费者的执行时间:更糟糕的是,我添加的消费者越多(想加快处理速度),我收到的消息越少 rate/s。

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

经验教训:

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

一般规则:

  • (1) calculate/estimate 交货时间。
  • (2) calculate/estimate 确认时间。
  • (3) calculate/estimate 消费时间。
  • qos = (1) + (2) + (3) / (3)

这将为您提供一个初始 qos 值,供您根据您的情况进行测试和调整。最终目标是使所有可用消费者的利用率达到 100%。