我在Wildfly 8.1(HornetQ)上使用捆绑的JMS实现来对大量文档进行OCR。
我想拥有3个MDB池,这些池使用Queue的消息,而文档为OCRed。每个MDB都以Apache commons-exec开始一个进程,并阻塞直到该进程退出。
在我的测试中,我有50条JMS消息(每个消息代表一个OCRed文档),它们在测试开始时就已加载到队列中。当处理开始时,在任何给定的时间,我都可以看到有3个占用大量CPU的OCR进程,每个MDB启动并阻止了它们。在某个时间点,大约20分钟后,其中一个OCR进程消失了,在任何给定时间只有2个存活。当剩下10条左右的JMS消息时,另一个OCR进程将停止,并且在任何给定时间只有1条。
最后,所有50个文档都已被OCRed使用,任何OCR流程或我的应用程序都不会抛出异常。
我发现这种行为很奇怪,因为我希望在耗时的JMS消息的任何时候都会有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 {
最佳答案
这与客户端(MDB)上的JMS消息缓冲有关。默认情况下,邮件缓冲是打开的,以避免网络延迟。但是,对于我的客户比较慢的情况,这不是问题。
这来自HornetQ documentation:
11.1.39。没有消费者缓冲
默认情况下,HornetQ使用方将来自服务器的消息缓冲在
客户端缓冲区,然后才能在客户端上实际收到它们
侧。这样可以提高性能,因为否则每次您打电话时
receive()或已经处理了MessageListener中的最后一条消息
onMessage()方法,HornetQ客户端必须将服务器转到
请求下一条消息,然后将其发送给客户端
一面,如果有的话。
这将涉及每个消息的网络往返,并减少
性能。因此,默认情况下,HornetQ将消息预提取到
每个消费者的缓冲区。
在某些情况下,缓冲是不可取的,HornetQ允许缓冲
关闭。这个例子说明了这一点。
作为文档的一部分,Github中有一个示例项目,其中使用方缓冲已关闭:link