ActiveMQ 消息组是跨多个使用者进行负载平衡的绝佳功能。简而言之:消息流根据消息中嵌入的组标识符(JMSXGroupID
)在单个队列的多个使用者之间进行分区。(因此,使用者 1 将获取带有JMSXGroupID = a
的所有消息,使用者 2 将获取带有JMSXGroupID = b
的所有消息,依此类推。
现在,假设您有 2 个队列:A
和B
,并假设在流经两个队列的消息中使用一致的JMSXGroupID
s 分类。代理选择在队列A
上JMSXGroupID = ABC
的使用者是否是来自代理选择在队列B
上JMSXGroupID = ABC
的同一连接的使用者?
我怀疑我问的问题的答案是"不"。有太多的变量在起作用:如果经纪人选择的消费者A
没有相应的消费者B
会发生什么?如果经纪人选择的消费者A
有多个相应的消费者B
,会发生什么?在这些情况下,没有明显的正确答案。
但是,我们可以模拟这种行为吗?例如,复合目标上的使用者可能是一个可行的解决方案 - 确保A
上的所有使用者和B
复合目标上消费A,B
并且您可能在做生意 - 但ActiveMQ似乎不支持从复合目标消费。
我找到的唯一解决方案就是简单地在一个队列上推送A
和B
的消息 - 称之为AB
- 并有一个独家消费者。您现在必须区分"A
消息"和"B
消息",但您可以使用标头轻松做到这一点。
但是,这种解决方案闻起来很有趣。(您现在必须假设生产者会尽职尽责地将特殊标头应用于他们的消息,或者修改您的有效负载。有没有一种解决方案可以确保跨两个独立队列的使用者A
和B
始终登陆同一连接?
正如您正确计算的那样,消息组仅适用于单个队列。多个队列之间没有协调。
通常,当您使用消息组时,您不仅要保证消息顺序,还要保证处理消息顺序 - 因此,假设特定实体的所有事件都是按顺序处理的。魔鬼总是在你的用例的细节中,但是将所有相关的消息放到一个队列中会给你你想要的结果。为了以不同的方式处理它们,您需要将某种多路复用逻辑放入您的使用者中,以根据消息有效负载做出决定 - 正如您所说,众所周知的标头是解决方案的良好候选者。
要绕过确保客户端显式设置此组件的先决条件,您可以做的是编写一段代表您执行此操作的 Camel 路由逻辑 - 这仅适用于添加到 ActiveMQ 5.9 的代理:组件。这个想法是生产者看到两个单独的队列 - A 和 B;路由逻辑将在放入消息时从这些队列中读取,适当地设置标头,并将它们重新路由到 C。路由逻辑实际上用作侦听器。
<route id="ConflateA">
<from uri="broker:queue:A"/>
<setHeader headerName="OriginalMessageSource">
<constant>A</constant>
</setHeader>
<to uri="broker:queue:C"/>
</route>
然后,您可以在多路复用逻辑中使用OriginalMessageSource
标头。