Wildfly JMS:当消息存在时,MDB bean 空闲

Posted

技术标签:

【中文标题】Wildfly JMS:当消息存在时,MDB bean 空闲【英文标题】:Wildfly JMS: MDB beans idle when messages exist 【发布时间】:2014-10-04 09:37:13 【问题描述】:

我在 Wildfly 8.1 (HornetQ) 上使用捆绑的 JMS 实现对大量文档进行 OCR。

我希望拥有一个由 3 个 MDB 组成的池,这些 MDB 使用一个队列的消息,其中包含要 OCRed 的文档。每个 MDB 使用 Apache commons-exec 启动一个进程并阻塞直到该进程退出。

在我的测试中,我有 50 条 JMS 消息(每条代表一个要进行 OCRed 处理的文档),它们在测试开始时加载到队列中。当处理开始时,在任何给定时间我都可以看到有 3 个 CPU 密集型 OCR 进程,每个 MDB 启动并阻止一个。在某个时间点,大约 20 分钟后,其中一个 OCR 进程消失了,在任何给定时间只有 2 个还活着。当剩余 10 条左右的 JMS 消息时,另一个 OCR 进程停止,并且在任何给定时间都只有 1 条。

最后,所有 50 个文档都已被 OCR,任何 OCR 进程或我的应用程序都没有抛出异常。

我觉得这种行为很奇怪,因为我预计在任何时间点都会有 3 个 OCR 进程在消耗 JMS 消息的时间(当然最后除外)。如果 JMS 消息在进入队列时被“分配”给 MDB 实例,而不是实时的,则可以解释这种行为。例如,如果每个 MDB 分配了大约 17 条消息。根据文档大小,一些 MDB 实例可能会提前完成并保持空闲状态而不消耗任何其他消息,而其他 MDB 实例仍然可以使用消息。

这是怎么回事?如果是,有没有办法改变这一点,以便在 MDB 实例完成处理消息时将消息分配给 MDB 实例?

@MessageDriven(activationConfig = 
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/csrOcrQueue"),
        @ActivationConfigProperty(propertyName = "minSession", propertyValue = "3"),
        @ActivationConfigProperty(propertyName = "maxSession", propertyValue = "3")
)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class OcrMessageListener implements MessageListener 

【问题讨论】:

【参考方案1】:

这与客户端 (MDB) 上的 JMS 消息缓冲有关。默认情况下,消息缓冲是打开的,以避免网络延迟。但是,对于我的客户端速度较慢的情况,这不是问题。

这是来自HornetQ documentation:

11.1.39。没有消费者缓冲

默认情况下,HornetQ 消费者缓存来自服务器的消息在一个 在客户端实际接收它们之前的客户端缓冲区 边。这可以提高性能,因为否则每次您调用 receive() 或已处理 MessageListener 中的最后一条消息 onMessage() 方法,HornetQ 客户端必须去服务器 请求下一条消息,然后将其发送给客户端 一边,如果有的话。

这将涉及每条消息的网络往返,并减少 表现。因此,默认情况下,HornetQ 将消息预取到 每个消费者的缓冲区。

在某些情况下缓冲是不可取的,HornetQ 允许它 关闭。这个例子证明了这一点。

Github 中有一个示例项目作为文档的一部分,其中消费者缓冲已关闭:link

【讨论】:

一个有趣的问题的好问题。也许您发布了错误的 SO 问题作为答案链接,或者答案实际上在嵌套文档链接之一中?我真的看不出该 SO 问题中所说的内容(导致部署失败的配置错误)与您的问题的消息缓冲解决方案之间有任何关联。 感谢@Gimby,修复了链接。 这是对我在 Wildfly 10 和 Artemis/ActiveMQ 中遇到的类似问题的一个很好且详细的解释,它的作用相同。有关当前配置示例,请参阅我在 ***.com/a/43585246/160799 的回答

以上是关于Wildfly JMS:当消息存在时,MDB bean 空闲的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly10中JMS队列的JNDI名称格式

MDB 和 JMS 的区别

Wildfly 上的 JMS 2.0 QueueBrowser 不返回消息

是否可以在运行时手动将消息驱动 bean 订阅到 JMS 队列/主题?

JavaEE- 带有 JMS 和 MDB 的消息传递系统

如何将 JMS 消息从 WildFly 10 发送到远程 ActiveMQ