【发布时间】:2013-01-08 15:30:28
【问题描述】:
我们在 CentOS 6.3 上使用 HornetQ 2.2.14。我们在应用服务器中遇到了 CPU 使用率过高的问题,并已使用分析器将其范围缩小到 HornetQ 消费者。
具体来说,我们在大约有 150 个消费者的空队列上快速连续调用此方法:
// Called about every 10ms per consumer.
javax.jms.MessageConsumer.receive(10);
这导致大约 2 个 NIO 工作线程回溯到 Netty,在我们原本空闲的 Tomcat 实例上消耗了大约 2 个 CPU 内核的 50%。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21939 tomcat 20 0 9061m 1.6g 16m R 55.4 21.2 1:06.88 java
21777 tomcat 20 0 9061m 1.6g 16m S 47.6 21.2 1:29.40 java
21777 tomcat 20 0 9061m 1.6g 16m S 7.3 21.2 1:33.41 java
21763 tomcat 20 0 9061m 1.6g 16m S 6.6 21.2 1:28.84 java
21682 tomcat 20 0 9061m 1.6g 16m S 4.3 21.2 0:26.70 java
问题是,在 Windows 上使用完全相同的代码和 Tomcat 配置,CPU 内核是空闲的。这让我相信这是一个 Linux/Netty/HornetQ 问题。以前有没有其他人见过这个,如果有,我该如何让它消失?
Linux 版本:CentOS 6.3 x64 Linux内核版本:Linux版本2.6.32-279.19.1.el6.x86_64
这是我测试过的 2 个 Java 版本,结果相同:
Java(TM) SE Runtime Environment (build 1.7.0_10-b18)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)
Java(TM) SE Runtime Environment (build 1.6.0_38-b05)
Java HotSpot(TM) 64-Bit Server VM (build 20.13-b02, mixed mode)
【问题讨论】:
-
忘了补充,这里是分析器识别的热点:org.hornetq.core.client.impl.ClientConsumerImpl.receive() 和 org.jboss.netty.channel.socket.nio。 SelectorUtil.select()
-
通过 切换 HornetQ 使用阻塞 IO 没有影响。现在不是 2 个 NIO 工作线程消耗 CPU,而是 2 个阻塞 IO 工作线程消耗相同数量的 CPU。一个客户端线程和一个服务器线程。
-
如果将超时值增加到 30 毫秒会发生什么。我问是因为如果超时值接近实时时钟的分辨率,可能会发生意外情况,我记得时钟在 10 毫秒左右运行。
-
CPU 使用率似乎与超时值成正比。如果我降低超时时间,或者使用 ClientConsumerImpl.receiveNoWait(),CPU 使用率会上升更多。如果我将超时时间增加到 30 毫秒,CPU 使用率会下降一点,但仍然高于预期。也就是说,它的使用率从 40% 下降到了 20%。
-
切换 HornetQ 连接和接受器工厂以使用“在 VM 中”而不是 Netty 只是为了进行测试,问题就消失了。这一定是 Linux 上的 Netty 的问题,因为它在 Windows 上运行良好。
标签: java jms netty nio hornetq