我们的ActiveMQ消费进程耗尽内存并死亡。ActiveMQ消费者OutOfMemoryException
我们有一个ActiveMQ主题,有一个发件人和两个接收者。从表面上看,所有的工作都很好---消息由两个接收者发送并拾取,但最终我们耗尽了所有的内存。堆转储显示LinkedList $ Node,AtomicReference,ActiveMQObjectMessage,MessageId和MessageDispatch的每个实例为136.2万个实例。同时,客户端消息队列全部为空或几乎为空。我认为1.362M可能在追踪未确认消息的列表中。该主题被指定为AUTO_ACKNOWLEDGE,所以我们试图确认,但可能失败。 (jmsSession = jmsConnection.createSession(false,Session.AUTO_ACKNOWLEDGE);)
堆转储显示垃圾似乎与客户的传入消息缓冲存在适度数(几千)相关联。这似乎与我们设置用于发送和消费类似对象的玩具程序中积累的这些对象的数量一致。他们累积了一段时间,然后得到GC'd,并且记忆在玩具或失败的程序中永远不会显着增长。
推测五种对象类型与ACKS相关联是否正确?如果是这样,尽管两个消费者明显完全消费,但是什么会导致对象保留在此结构中?有什么方法可以取消我们认为已设置的AUTO_ACKNOWLEDGE?顺便说一句,一个消费者是同步的,使用receive(),另一个是异步的,使用onMessage()。
一个可能令人误解的症状是ActiveMQ GUI显示只有一次出队的对象,尽管存在两个消费者。玩具显示每个队列中有两个出队队列。但是,该程序本身表示他们已阅读了预期的次数。
// creating the async consumer.
connAmq = createActiveMqConnection();
connAmq.start();
session = connAmq.createSession(true, Session.AUTO_ACKNOWLEDGE);
Destination topic = session.createTopic(appProperties.getActiveMqTopicQuotesName());
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(this);
public void onMessage(Message message) {
...
try {
if (message instanceof ObjectMessage) {
ObjectMessage msg = (ObjectMessage)message;
if (msg instanceof Foo) {
Foo quote = (Foo)msg.getObject();
...
}
}
}
...
}
// creating the sync consumer
jmsConnection = mActiveMQConnectionFactory.createTopicConnection();
jmsConnection.start();
jmsSession = jmsConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
jmsDestination = jmsSession.createTopic(name);
jmsMessageConsumer = jmsSession.createConsumer(jmsDestination);
//the code for consuming looks like this for the synchronous consumer
while(true)
ObjectMessage m = (ObjectMessage) jmsMessageConsumer.receive();
if (m != null)
Process(m.getObject());
}
谢谢---但这是我的一个错字。失败的代码设置事务值为false。我简化了,因为它是一个变量,而不是字面的“错误”。它看起来像:session = connAmq.createSession(false,Session.AUTO_ACKNOWLEDGE); –
session = connAmq.createSession(false,Session.AUTO_ACKNOWLEDGE); –