ActiveMQ 浏览器需要很长时间才能上次 .hasMoreElements()
ActiveMQ browser needs long time for last .hasMoreElements()
我尝试为 ActiveMQ 实现一个队列浏览器。
下面显示的代码应显示名为 'Q1' 的队列中的文本消息。里面有两条消息。通常它可以工作,但最后一个 e.hasMoreElements()
调用最多需要 20 秒。我想每 500 毫秒更新一次列表。
为什么这么慢?
当我在浏览器视图中按 'update' 立即显示 http://localhost:8161/admin/browse.jsp?JMSDestination=Q1
e.hasMoreElements()
returns .这里发生了什么?如何实现'realtime'视图?
//init:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
Queue queue = session.createQueue("Q1");
boolean run = true;
while (run) {
LOG.info("--------------------------------------------------------------------------------");
QueueBrowser browser = session.createBrowser(queue);
Enumeration e = browser.getEnumeration();
while (e.hasMoreElements()) { //<- very slow before returning false after last message. why?
Object o = e.nextElement();
if (o instanceof ActiveMQTextMessage) {
LOG.info(((ActiveMQTextMessage) o).getText());
} else {
LOG.info(o.toString());
}
}
Thread.sleep(500);
browser.close();
}
session.close();
connection.close();
经过一些研究和尝试后,我转向了更新的 JMX 技术。穿过队列时没有性能问题。
一些代码:
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url, null);
connector.connect();
connection = connector.getMBeanServerConnection();
ObjectName name = new ObjectName(getObjectNameByBrokerName(brokerName));
brokerMBean = (BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
ObjectName[] objNames = brokerMBean.getQueues();
for (ObjectName objName : objNames) {
QueueViewMBean queueMBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, objName, QueueViewMBean.class, true);
System.out.println(queueMBean.getName());
}
您必须在配置中激活 jmx。默认情况下它是停用的。
根据我之前的评论,我发现在连接工厂上调用 setTransactedIndividualAck(true) 可以解决问题
ActiveMQConnectionFactory cf2 = new ActiveMQConnectionFactory(...);
cf2.setTransactedIndividualAck(true);
我不确定这是解决问题的正确方法,但至少它现在有效。在此处查看 ActiveMQ 用户论坛上的消息:
http://activemq.2283324.n4.nabble.com/JMS-browser-getEnumeration-hasMoreElements-takes-15s-on-last-element-td4709969.html
我遇到了同样的问题。但是更改会话确认消除了延迟。
试试这个:
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
我发现在我的 hasMoreElements()
循环中调用 Session.commit()
停止使用 activemq-broker
版本 5.14.5
:
的挂起
while(enumeration.hasMoreElements()) {
final Message message = (Message)enumeration.nextElement();
final TextMessage textMessage = (TextMessage)message;
session.commit();
}
我做了更多研究,看看这是否是 ActiveMQ 的错误,发现 activemq-broker
版本 5.15.1
没有挂起,即使在每次迭代后都没有调用 commit()
。代理的所有先前版本在对 hasMoreElements()
的最终调用时挂起。似乎贡献者并没有故意解决这个特定问题,因为 bug report on JIRA that the change referenced was for something different. The change that fixed this issue 更改了 org.apache.activemq.broker.region.Queue
class 的 iterate()
方法的一部分来自:
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
}
到
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
} else {
wakeup();
}
为了确认这是解决问题的更改,我转到以前的版本 5.15.0
并强制使用调试器调用 wakeup()
并调用 hasMoreElements()
没挂。
我尝试为 ActiveMQ 实现一个队列浏览器。
下面显示的代码应显示名为 'Q1' 的队列中的文本消息。里面有两条消息。通常它可以工作,但最后一个 e.hasMoreElements()
调用最多需要 20 秒。我想每 500 毫秒更新一次列表。
为什么这么慢?
当我在浏览器视图中按 'update' 立即显示 http://localhost:8161/admin/browse.jsp?JMSDestination=Q1
e.hasMoreElements()
returns .这里发生了什么?如何实现'realtime'视图?
//init:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
Queue queue = session.createQueue("Q1");
boolean run = true;
while (run) {
LOG.info("--------------------------------------------------------------------------------");
QueueBrowser browser = session.createBrowser(queue);
Enumeration e = browser.getEnumeration();
while (e.hasMoreElements()) { //<- very slow before returning false after last message. why?
Object o = e.nextElement();
if (o instanceof ActiveMQTextMessage) {
LOG.info(((ActiveMQTextMessage) o).getText());
} else {
LOG.info(o.toString());
}
}
Thread.sleep(500);
browser.close();
}
session.close();
connection.close();
经过一些研究和尝试后,我转向了更新的 JMX 技术。穿过队列时没有性能问题。
一些代码:
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
JMXConnector connector = JMXConnectorFactory.connect(url, null);
connector.connect();
connection = connector.getMBeanServerConnection();
ObjectName name = new ObjectName(getObjectNameByBrokerName(brokerName));
brokerMBean = (BrokerViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, name, BrokerViewMBean.class, true);
ObjectName[] objNames = brokerMBean.getQueues();
for (ObjectName objName : objNames) {
QueueViewMBean queueMBean = (QueueViewMBean) MBeanServerInvocationHandler.newProxyInstance(connection, objName, QueueViewMBean.class, true);
System.out.println(queueMBean.getName());
}
您必须在配置中激活 jmx。默认情况下它是停用的。
根据我之前的评论,我发现在连接工厂上调用 setTransactedIndividualAck(true) 可以解决问题
ActiveMQConnectionFactory cf2 = new ActiveMQConnectionFactory(...);
cf2.setTransactedIndividualAck(true);
我不确定这是解决问题的正确方法,但至少它现在有效。在此处查看 ActiveMQ 用户论坛上的消息: http://activemq.2283324.n4.nabble.com/JMS-browser-getEnumeration-hasMoreElements-takes-15s-on-last-element-td4709969.html
我遇到了同样的问题。但是更改会话确认消除了延迟。
试试这个:
Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
我发现在我的 hasMoreElements()
循环中调用 Session.commit()
停止使用 activemq-broker
版本 5.14.5
:
while(enumeration.hasMoreElements()) {
final Message message = (Message)enumeration.nextElement();
final TextMessage textMessage = (TextMessage)message;
session.commit();
}
我做了更多研究,看看这是否是 ActiveMQ 的错误,发现 activemq-broker
版本 5.15.1
没有挂起,即使在每次迭代后都没有调用 commit()
。代理的所有先前版本在对 hasMoreElements()
的最终调用时挂起。似乎贡献者并没有故意解决这个特定问题,因为 bug report on JIRA that the change referenced was for something different. The change that fixed this issue 更改了 org.apache.activemq.broker.region.Queue
class 的 iterate()
方法的一部分来自:
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
}
到
// are we done browsing? no new messages paged
if (!added || browser.atMax()) {
browser.decrementQueueRef();
browserDispatches.remove(browserDispatch);
} else {
wakeup();
}
为了确认这是解决问题的更改,我转到以前的版本 5.15.0
并强制使用调试器调用 wakeup()
并调用 hasMoreElements()
没挂。