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

Tus*_*shu 6 java jvm jms hornetq netty

组态

我在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>
Run Code Online (Sandbox Code Playgroud)

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

问题

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

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

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

欢迎任何建议,并提前感谢.

the*_*472 2

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

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

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