MQ出现OOM问题之二 ActiveMQOOM
程序员文章站
2024-01-21 15:50:46
...
【问题】
MQ长期运行后,出现老代GC不掉的现象分析。
通过HA工具分析后,发现对象TransportConnection占用绝对部分heap空间。
问题分解:实际可以归结为两个方面的问题,如下:
1、VMTransport的建立是由网桥建立动作触发的;即【VMTransport】对象在内存中的增加;
2、VMTransport能否被回收和内存中该对象的引用有关;即【VMTransport】对象在内存中的减少;
【分析】
(1)VMTransport和TransportConnection数量是1:1的关系。
(2)【jms.pool.ConnectionPool】和【 jms.pool.ConnectionPool$1】同时存在,正常的情况下,仅后者出现,即内部类对象。
(3)VMTransport数量为奇数,而仅通过网桥触发的VMTransport是偶数,即成对出现的;
(4)建网桥关键字【Establishing】
(5)通过网桥触发的VMTransport是可以被GC掉的,验证时可以触发System.gc();
(6)MutexTransport如何被ResponseCorrelator所引用?==>相互引用
(7)ResponseCorrelator和MutexTransport都是继承自TransportFilter,怎么会相互引用呢?==>正常
(8)分析正常heapdump和异常的heapdump,发现【FMQConnection】的引用不同,正常时,类【FMQConnection】的owner【ResponseCorrelator】,不正常时,其owner变为【jms/pool/ConnectionPool】导致该类引用在连接池中缓存,回收不掉的问题发生。
【注意】
(1)区分:FMQConnection和broker.TransportConnection以及VMTransport的关系
(2)正常情况下:【FMQConnection】和【ResponseCorrelator】相互引用,发生问题时【FMQConnection】owner为【jms.pool.ConnectionPool】导致无法回收。
(3)VMTransport由使用vm通道时触发生成,如:uri调用vm://<brokerName>或者建立网桥时也会触发vm://<brokerName>
(4)问题发生的原因,【VMTransport】引用了【FMQConnection】,而【FMQConnection】来自【jms.pool.ConnectionPool】,在连接池中,将【FMQConnection】的超时时间设置为了0,导致其不能被回收,从而只要【VMTransport】引用到这种来自连接池的【FMQConnection】对象,
,就有可能只增长而不减少,即回收不掉。
(5)解决方法:
>>>同JVM时,客户端和broker间不使用连接池,直接使用VMTransport产生FMQConnection;
>>>同JVM时,uri采用vm通道,并且要采用连接池,建议连接池中的连接是可回收的,即设置一个超时时间,而不是永不过期;==>目前暂不起作用;
===>建议使用vm通道时,不采用连接池; ===>调整目标是【FMQConnection】不要关联到连接池对象【jms.pool.ConnectionPool】,因为使用了连接池,连接【FMQConnection】也是共享的,而不是单独由连接池提供的。
>>>考虑在MQ配置中,预先添加VM通道,以免客户端首次创建该通道;
>>>如果非要形式上用连接池,则建网桥的动作在通过vm通道创建连接池之前执行;
【问题聚焦】==>和thread context有关还是和触发VM通道的建立次序有关?
【总结】和VM通道的建立次序有关,考虑在MQ配置中,预先添加VM通道,以免客户端因首次创建该通道,并且让【FMQConnection】引用了来自连接池之类的引用不释放对象;
MQ配置通道如下:
//////////begin///////
<transportConnector name="vm" uri="vm://broker-${fmq.brokername}"/>
//////////end/////////
日志如下:
///////////begin//////
Connector openwire started and configured URI is tcp://0.0.0.0:61616
Connector vm started and configured URI is vm://broker-cnd
//////////end/////////
MQ长期运行后,出现老代GC不掉的现象分析。
通过HA工具分析后,发现对象TransportConnection占用绝对部分heap空间。
问题分解:实际可以归结为两个方面的问题,如下:
1、VMTransport的建立是由网桥建立动作触发的;即【VMTransport】对象在内存中的增加;
2、VMTransport能否被回收和内存中该对象的引用有关;即【VMTransport】对象在内存中的减少;
【分析】
(1)VMTransport和TransportConnection数量是1:1的关系。
(2)【jms.pool.ConnectionPool】和【 jms.pool.ConnectionPool$1】同时存在,正常的情况下,仅后者出现,即内部类对象。
(3)VMTransport数量为奇数,而仅通过网桥触发的VMTransport是偶数,即成对出现的;
(4)建网桥关键字【Establishing】
(5)通过网桥触发的VMTransport是可以被GC掉的,验证时可以触发System.gc();
(6)MutexTransport如何被ResponseCorrelator所引用?==>相互引用
(7)ResponseCorrelator和MutexTransport都是继承自TransportFilter,怎么会相互引用呢?==>正常
(8)分析正常heapdump和异常的heapdump,发现【FMQConnection】的引用不同,正常时,类【FMQConnection】的owner【ResponseCorrelator】,不正常时,其owner变为【jms/pool/ConnectionPool】导致该类引用在连接池中缓存,回收不掉的问题发生。
【注意】
(1)区分:FMQConnection和broker.TransportConnection以及VMTransport的关系
(2)正常情况下:【FMQConnection】和【ResponseCorrelator】相互引用,发生问题时【FMQConnection】owner为【jms.pool.ConnectionPool】导致无法回收。
(3)VMTransport由使用vm通道时触发生成,如:uri调用vm://<brokerName>或者建立网桥时也会触发vm://<brokerName>
(4)问题发生的原因,【VMTransport】引用了【FMQConnection】,而【FMQConnection】来自【jms.pool.ConnectionPool】,在连接池中,将【FMQConnection】的超时时间设置为了0,导致其不能被回收,从而只要【VMTransport】引用到这种来自连接池的【FMQConnection】对象,
,就有可能只增长而不减少,即回收不掉。
(5)解决方法:
>>>同JVM时,客户端和broker间不使用连接池,直接使用VMTransport产生FMQConnection;
>>>同JVM时,uri采用vm通道,并且要采用连接池,建议连接池中的连接是可回收的,即设置一个超时时间,而不是永不过期;==>目前暂不起作用;
===>建议使用vm通道时,不采用连接池; ===>调整目标是【FMQConnection】不要关联到连接池对象【jms.pool.ConnectionPool】,因为使用了连接池,连接【FMQConnection】也是共享的,而不是单独由连接池提供的。
>>>考虑在MQ配置中,预先添加VM通道,以免客户端首次创建该通道;
>>>如果非要形式上用连接池,则建网桥的动作在通过vm通道创建连接池之前执行;
【问题聚焦】==>和thread context有关还是和触发VM通道的建立次序有关?
【总结】和VM通道的建立次序有关,考虑在MQ配置中,预先添加VM通道,以免客户端因首次创建该通道,并且让【FMQConnection】引用了来自连接池之类的引用不释放对象;
MQ配置通道如下:
//////////begin///////
<transportConnector name="vm" uri="vm://broker-${fmq.brokername}"/>
//////////end/////////
日志如下:
///////////begin//////
Connector openwire started and configured URI is tcp://0.0.0.0:61616
Connector vm started and configured URI is vm://broker-cnd
//////////end/////////