Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RabbitMQ(Java)多用户性能问题_Java_Mongodb_Rabbitmq_Amqp_Mongodb Java - Fatal编程技术网

RabbitMQ(Java)多用户性能问题

RabbitMQ(Java)多用户性能问题,java,mongodb,rabbitmq,amqp,mongodb-java,Java,Mongodb,Rabbitmq,Amqp,Mongodb Java,我正在实现一个日常作业,该作业从MongoDB(大约30万个文档)获取数据,并为每个文档在RabbitMQ队列上发布消息。 另一方面,我有一些消费者在同一个队列中,理想情况下应该并行工作 一切正常,但没有我想象的那么多,特别是在消费者表现方面 以下是我声明队列的方式: rabbitMQ.getChannel().queueDeclare(QUEUE_NAME, true, false, false, null); 以下是发布的方式: rabbitMQ.getChannel().basicPub

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

一切正常,但没有我想象的那么多,特别是在消费者表现方面

以下是我声明队列的方式:

rabbitMQ.getChannel().queueDeclare(QUEUE_NAME, true, false, false, null);
以下是发布的方式:

rabbitMQ.getChannel().basicPublish("", QUEUE_NAME, null, body.getBytes());
因此,用于声明队列的通道用于发布所有消息

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

因此,我为每个消费者创建了一个新的渠道,并通过日志证实了这一点:

...
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秒

我是否缺少RabbitMQ中线程的主要概念?或者任何可能仍处于默认值的特定配置? 我在这几天就开始了,所以这可能是可能的

请注意,我很幸运,我可以控制发布和消费部分:)

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


谢谢你的帮助

RabbitMQ通道和使用者的设置最终是正确的:因此每个使用者有一个通道

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

这会延迟一些使用者的执行时间:即使最糟糕的是,我添加的使用者越多(考虑加快处理速度),得到的消息速率也越低

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

经验教训:

  • 为发布者创建单独的频道
  • 为每个消费者创建单独的频道
  • 让RabbitMQ为使用者管理线程(->您可以在主线程上实例化它们)
  • (如果可能)停止发布,让队列有100%的时间与消费者打交道
  • 为每个用户通道设置qos>1。但这实际上取决于您的场景和体系结构:您必须进行一些性能测试
一般来说:

  • (1) 计算/估计交货时间
  • (2) 计算/估计确认时间
  • (3) 计算/估计消费者时间
  • 服务质量=(1)+(2)+(3)/(3)

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

您是否查看了使用消息的应用程序的堆栈跟踪?是否有10个线程正在读取RabbitMQ?这10个线程在做什么?我怀疑在应用程序逻辑中有什么东西阻塞了消费者。如果随着时间的推移查看一些堆栈跟踪,您应该会得到一个查找位置的提示。@Robmore仔细检查堆栈跟踪,我看到消费者为了查找和更新mongodb文档而相互竞争。事实上,如果我把这部分注释掉,我每秒可以消耗几十条消息。我现在正在重构代码,尝试在发布端移动db更新,让使用者只执行最简单的任务。在一个通道上只让一个客户端使用者在客户端中分派工作如何?
...
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@bdd2027
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@5d1b9c3d
com.rabbitmq.client.impl.recovery.AutorecoveringChannel@49a26d19
...