为什么Direct ByteBuffer在通往OOM的HornetQ服务器上不断增加?

时间:2016-01-24 15:55:12

标签: java jvm jms netty hornetq

配置

我在Ubuntu 12.04.3 LTS(GNU / Linux 3.8.0-29-generic x86_64)上设置了一个独立的HornetQ(2.4.7-Final)集群。该实例有16GB RAM和2个内核,我已经为JVM分配了-Xms5G -Xmx10G。

以下是HornetQ配置中的地址设置:

   <address-settings>
      <address-setting match="jms.queue.pollingQueue">
         <dead-letter-address>jms.queue.DLQ</dead-letter-address>
         <expiry-address>jms.queue.ExpiryQueue</expiry-address>
         <redelivery-delay>86400000</redelivery-delay>
         <max-delivery-attempts>10</max-delivery-attempts>
         <max-size-bytes>1048576000</max-size-bytes>
         <page-size-bytes>10485760</page-size-bytes>
         <address-full-policy>PAGE</address-full-policy>
         <message-counter-history-day-limit>10</message-counter-history-day-limit>
      </address-setting>
      <address-setting match="jms.queue.offerQueue">
         <dead-letter-address>jms.queue.DLQ</dead-letter-address>
         <expiry-address>jms.queue.ExpiryQueue</expiry-address>
         <redelivery-delay>3600000</redelivery-delay>
         <max-delivery-attempts>25</max-delivery-attempts>
         <max-size-bytes>1048576000</max-size-bytes>
         <page-size-bytes>10485760</page-size-bytes>
         <address-full-policy>PAGE</address-full-policy>
         <message-counter-history-day-limit>10</message-counter-history-day-limit>
      </address-setting>
      <address-setting match="jms.queue.smsQueue">
         <dead-letter-address>jms.queue.DLQ</dead-letter-address>
         <expiry-address>jms.queue.ExpiryQueue</expiry-address>
         <redelivery-delay>3600000</redelivery-delay>
         <max-delivery-attempts>25</max-delivery-attempts>
         <max-size-bytes>1048576000</max-size-bytes>
         <page-size-bytes>10485760</page-size-bytes>
         <address-full-policy>PAGE</address-full-policy>
         <message-counter-history-day-limit>10</message-counter-history-day-limit>
      </address-setting>
      <!--default for catch all-->
      <!-- delay redelivery of messages for 1hr -->
      <address-setting match="#">
         <dead-letter-address>jms.queue.DLQ</dead-letter-address>
         <expiry-address>jms.queue.ExpiryQueue</expiry-address>
         <redelivery-delay>3600000</redelivery-delay>
         <max-delivery-attempts>25</max-delivery-attempts>
         <max-size-bytes>1048576000</max-size-bytes>
         <page-size-bytes>10485760</page-size-bytes>
         <address-full-policy>PAGE</address-full-policy>
         <message-counter-history-day-limit>10</message-counter-history-day-limit>
      </address-setting>
   </address-settings>

其他10个队列绑定到通配符指定的默认地址。

问题

在一段时间内,Direct ByteBuffer内存的大小逐渐增加,甚至占用交换空间,最终抛出OutOfMemoryError(&#34;直接缓冲内存&#34;)。

我已经尝试过很多JVM和JMS调优但是徒劳无功。即使为JVM指定-XX:MaxDirectMemorySize = 4G也会导致早期的OOME出于同样的原因。似乎没有读取ByteBuffer或者GC没有声明未引用的内存。

以前有人遇到过同样的问题吗?

欢迎任何建议,并提前致谢。

1 个答案:

答案 0 :(得分:2)

我对hornetq的内部结构一无所知,所以这个答案只涵盖了DBB:

  • 它是一个普通的泄漏,DBB对象仍然可以访问,因此不会被释放。这可能是由于应用程序中的错误或错误使用造成的。
    通常的方法是进行堆转储并确定使对象保持活动的原因。

  • 缓冲区变得无法访问,但垃圾收集器执行旧的gen集合很少,直到它们实际被收集并且本机内存被释放需要很长时间。如果服务器以-XX:+DisableExplicitGC运行,则还会在达到MaxDirectMemorySize限制时抑制最后一次尝试Full GC。
    调整GC以更频繁地运行以确保及时释放DBB可以解决这种情况。