虚拟主题
ActiveMQ 5.x 中的虚拟主题(虚拟目的地的一个专门化)通常解决两个不同的但相关的问题。让我们依次来看。
共享访问 JMS 持久主题订阅
在 JMS1.1 中,持久订阅由 clientId 和 subscriptionName 对标识。clientId 组件对于代理上的连接必须是唯一的。这意味着订阅是独占的。无法跨消费者负载均衡消息流,快速故障转移也很困难,因为代理上的现有连接状态需要先被处置。使用虚拟主题,每个订阅的消息流都会被重定向到一个队列。
在 Artemis 中,有两个替代方案:新的 JMS 2.0 API 或通过 FQQN 直接访问订阅队列。
JMS 2.0 共享订阅
JMS 2.0 添加了共享订阅的可能性,并提供了新的 API,这些 API 在 Artemis 中得到完全支持。
完全限定队列名称 (FQQN)
其次,Artemis 在内部使用每个主题订阅者的队列模型,并且可以使用其完全限定队列名称 (FQQN) 直接访问订阅队列。
例如,主题 VirtualTopic.Orders
的订阅 A
的默认 5.x 消费者目的地
...
Queue subscriptionQueue = session.createQueue("Consumer.A.VirtualTopic.Orders");
session.createConsumer(subscriptionQueue);
将被替换为由地址和队列组成的 Artemis FQQN。
...
Queue subscriptionQueue = session.createQueue("VirtualTopic.Orders::Consumer.A.VirtualTopic.Orders");
session.createConsumer(subscriptionQueue);
这确实需要修改消费者使用的目的地名称,这不是理想的选择。如果无法修改 OpenWire 客户端,Artemis 支持 OpenWire 协议处理程序上的虚拟主题通配符过滤器机制,该机制将自动将消费者目的地转换为相应的 FQQN。格式是逗号分隔的字符串对列表,用分号分隔。每对标识一个过滤器以匹配虚拟主题消费者目的地,以及一个指定路径匹配数以终止消费者队列身份的整数。
例如:对于默认的 5.x 虚拟主题消费者前缀 Consumer.*.
,参数 virtualTopicConsumerWildcards
应该是:Consumer.*.>;2
。但是,有一个注意事项,因为此值需要在 xml 配置中以 uri 编码。任何不安全的 url 字符,在本例中为:> ;
需要使用其十六进制代码点表示进行转义;导致值为 Consumer.*.%3E%3B2
。这样,消费者目的地 Consumer.A.VirtualTopic.Orders
将转换为 FQQN VirtualTopic.Orders::Consumer.A.VirtualTopic.Orders
。
代理网络中的持久主题订阅者
5.x 中的存储转发网络桥接器为每个目的地创建一个持久订阅者。随着需求在网络中迁移,在网络中的每个节点上都会创建重复的持久订阅,但它们不会迁移。最终结果会导致重复的消息存储,最终导致重复的传递,这不是一件好事。当持久订阅映射到虚拟主题订阅者队列时,队列可以迁移,从而避免此问题。
在 Artemis 中,由于持久订阅被建模为队列,因此不会出现此问题。