我正在实现从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的交付/消费性能,而是我注意到了:
我是否错过了RabbitMQ中线程的主要概念?或者任何可能仍处于默认值的特定配置? 我很少见,所以这可能是可能的。
请注意,我处于幸运的位置,我可以控制出版和消费部分:)
我在本地使用RabbitMQ 3.7.3,因此它不会出现任何网络延迟问题。
感谢您的帮助!
答案 0 :(得分:0)
RabbitMQ频道和消费者的设置最终是正确的:每个消费者都有一个频道。
问题在于消费者调用同步方法来查找和更新MongoDB文档。
这延迟了一些消费者的执行时间:即使最糟糕的是,我添加的消费者越多(想加快处理速度),我获得的消息率就越低。
我已将MongoDB部分移到了发布方面,我不必关心同步,因为它只是由一个发布者按顺序完成的。我的交付率略有下降,但现在只有5名消费者,我很容易达到50-60 / s的确认率。
经验教训:
作为一般规则:
这将为您提供初始qos值,以根据您的方案进行测试和调整。最终目标是为所有可用的消费者提供100%的利用率。