java - Linux 高 CPU 负载上的 HornetQ 消费者

标签 java jms netty nio hornetq

我们在 CentOS 6.3 上使用 HornetQ 2.2.14。我们的应用服务器中遇到了 CPU 使用率过高的问题,并使用分析器将问题范围缩小到了 HornetQ Consumer。

具体来说,我们在大约有 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)

最佳答案

IMO 你应该使用 MessageListener.. 或者只是阻塞更长的时间,比如 10 秒...

... 重复 10 毫秒对您的系统来说是一个巨大的爆发。特别是客户端每次都会向服务器发送回调。

让消息系统为您完成工作,即当消息到达时让它给您打电话。如果您每 10 毫秒轮询一次系统却毫无结果,那么您就不能期待任何其他事情。

正如您所指出的,这是您问题的罪魁祸首:

consumer.receive(10);

算一下,每个使用 receive(10) 攻击服务器的消费者都会让服务器每秒向你发送 100 条消息,告诉你……我是空的。

receive(10) 将进行一次往返以保证没有消息在传输中。因此,您正在用空消息攻击服务器。

根据您强制使用的参数,您的应用程序不应表现良好。对于任何保证您在返回 null 之前 receive(10) 为空的消息解决方案都是如此。

关于java - Linux 高 CPU 负载上的 HornetQ 消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14508749/

相关文章:

netty - 在同一台开发机器上运行多个 Netty 客户端和一个服务器

java - 端点没有适配器;您的端点是否使用 @Endpoint 注释,或者它是否实现了受支持的接口(interface),如 MessageHandler 或 PayloadEndpoint?

transactions - WSO2 中的 JMS 消费者事务

java - 具有多个 Tomcat 的 Activemq (JMS)

java - Vert.x 从 TCP 的部分字节读取

http - Netty ChannelUpstreamHandler 和 HTTP 流水线

java - Netezza 流式处理结果集

java - 在java smslib中访问和更改用户数据头

Java:在子类化中使用通用通配符

java - 从 Firebase 真实数据库中获取值以用它们制作图表