在使用artemis的spring引导应用程序中,我们尽量避免包含太多消息的队列。目的是仅在队列中当前消息数低于特定限制(例如 100 条消息(时才放入新消息。但是,这似乎不起作用,但我们不知道为什么或实现该功能的"正确"方法是什么。以下代码提取的消息数始终为 0,尽管在 gui 中有消息。
为了重现该问题,我在本地安装了apache-artemis-2.13.0。
我们正在做如下的事情
if (!jmsUtil.queueHasNotMoreElementsThan(QUEUE_ALMOST_EMPTY_MAX_AMOUNT, reprocessingMessagingProvider.getJmsTemplate())) {
log.info("Queue has too many messages. Will not send more...");
return;
}
jmsUtil 的实现方式如下
public boolean queueHasNotMoreElementsThan(int max, JmsOperations jmsTemplate) {
return Boolean.TRUE.equals(
jmsTemplate.browse((session, queueBrowser) -> {
Enumeration enumeration = queueBrowser.getEnumeration();
return notMoreElemsThan(enumeration, max);
}));
}
private Boolean notMoreElemsThan(Enumeration enumeration, int max) {
for (int i = 0; i <= max; i++) {
if (!enumeration.hasMoreElements()) {
return true;
}
enumeration.nextElement();
}
return false;
}
作为检查,我还使用以下方法直接为我提供了队列中的消息数。
public int countPendingMessages(String destination, JmsOperations jmsTemplate) {
Integer totalPendingMessages = jmsTemplate.browse(destination,
(session, browser) -> Collections.list(browser.getEnumeration()).size());
int messageCount = totalPendingMessages == null ? 0 : totalPendingMessages;
log.info("Queue {} message count: {}", destination, messageCount);
return messageCount;
}
提取队列大小的方法似乎也被其他人使用,并且基于 QueueBrowser: 的文档The getEnumeration method returns a java.util.Enumeration that is used to scan the queue's messages.
以上是如何获取队列大小的正确方法吗?如果是这样,问题的原因可能是什么?如果不是,应如何查询队列大小?春天是否提供了访问队列的其他可能性?
更新:我阅读了另一篇文章和文档,但我不知道如何获取客户端会话。
使用QueueBrowser
来计算队列中的消息数有一些注意事项。第一个在JavaDocQueueBrowser
中指出:
扫描完成后,邮件可能会到达并过期。JMS API 不要求枚举的内容是队列内容的静态快照。这些更改是否可见取决于 JMS 提供程序。
因此,计数可能不是 100% 准确的。
还有一个事实是,从技术上讲,队列中可能仍有消息已发送给消费者但尚未确认。这些消息不会被QueueBrowser
计算,即使如果相关使用者关闭其连接,它们也可能在任何时候被取消回队列。
简单地说,JMS API 并没有提供一种真正可靠的方法来确定队列中的消息数量。此外,"Spring JMS"与JMS API相关联。它没有任何其他方式与 JMS 代理交互。鉴于此,您需要使用特定于提供程序的机制来确定消息计数。
ActiveMQ Artemis有一个丰富的管理API,可以通过特别构造的JMS消息等方式进行访问。您可以在examples/features/standard/management
目录中随 ActiveMQ Artemis 一起附带的"管理"示例中看到此操作。它演示如何使用 JMS 资源和特定于提供程序的帮助程序类来获取 JMS 队列的消息计数。这基本上与您提到的另一篇文章中给出的解决方案相同,但它使用 JMS API 而不是 ActiveMQ Artemis "核心"API。