如何在 sending/subscribing 到 JMS 对象、ActiveMQ Artemis 和 STOMP 时指定主题或队列

How to specify topic or queue when sending/subscribing to a JMS object, ActiveMQ Artemis and STOMP

我正在使用 ActiveMQ Artemis 消息传递系统,并且正在使用 STOMP (stomp.py) 测试我的设置。

我在名为 Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic 的 Artemis 上创建了一个 "address",并为其附加了两个队列:

这里是导出的绑定:

<bindings>
   <address-binding routing-types="ANYCAST" name="DLQ" id="2"/>
   <address-binding routing-types="ANYCAST" name="ExpiryQueue" id="6"/>
   <address-binding routing-types="MULTICAST" name="activemq.notifications" id="10"/>
   <address-binding routing-types="MULTICAST" name="Site.SOF.Order.Fulfillment.Submission.Topic" id="92"/>
   <queue-binding address="Site.SOF.Order.Fulfillment.Submission.Topic" filter-string="" name="Site.SOF.Order.Fulfillment.Submission.log.Queue" id="97" routing-type="MULTICAST"/>
   <queue-binding address="DLQ" filter-string="" name="DLQ" id="4" routing-type="ANYCAST"/>
   <queue-binding address="ExpiryQueue" filter-string="" name="ExpiryQueue" id="8" routing-type="ANYCAST"/>
   <queue-binding address="Site.SOF.Order.Fulfillment.Submission.Topic" filter-string="" name="Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Queue" id="94" routing-type="MULTICAST"/>
</bindings>

我创建了一个可以访问 Site.*

的用户

那么如何访问队列?例如,如果我像这样使用 stomp.py 命令行工具:

> subscribe Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue

我收到错误:

[username] does not have permission='CREATE_ADDRESS' on address Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue

所以我尝试在前面添加 /queue/,正如我在教程中看到的那样

> subscribe /queue/Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue

但我得到同样的错误:

[username] does not have permission='CREATE_ADDRESS' on address /queue/Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue

我可以毫不费力地发送到 topic/address。以下结果导致 "hello" 消息出现在两个队列中。

send Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic "hello"

这是我遗漏的命名约定吗?或者指定主题与队列的方法?我在这里遗漏了什么太明显而无法清楚地记录下来的东西?

让我先提供一些背景信息...

ActiveMQ Artemis 地址模型包括 3 个主要元素 - 地址、队列和路由类型。这些是低级实体,用于为代理支持的所有不同协议和配置实现所有不同语义。

相比之下,STOMP 只支持模棱两可的 "destinations." STOMP 1.2 specification 关于目的地的说明:

A STOMP server is modelled as a set of destinations to which messages can be sent. The STOMP protocol treats destinations as opaque string and their syntax is server implementation specific. Additionally STOMP does not define what the delivery semantics of destinations should be. The delivery, or “message exchange”, semantics of destinations can vary from server to server and even from destination to destination. This allows servers to be creative with the semantics that they can support with STOMP.

在核心地址模型中,消息被发送到地址并从队列中使用。地址和队列是独立命名的,因此核心生产者和消费者使用的名称可以不同。

ActiveMQ Artemis 支持 STOMP 目的地的点对点和 pub/sub 语义。您可以在 latest ActiveMQ Artemis STOMP documentation.

中阅读有关如何配置这些语义的更多信息

在 STOMP 点对点用例中,消息被发送到目的地并从同一目的地被消费。 STOMP生产者和消费者使用的名称相同。为了支持这些语义,代理使用核心地址和核心 anycast 队列 同名 .

在 STOMP pub/sub 用例中,客户端在目的地创建订阅,然后它可以使用该订阅来接收发送到该目的地的消息。 STOMP 订阅者和生产者使用的名称相同。为了支持这些语义,代理使用核心地址和核心多播队列具有不同的名称。核心队列的名称由代理自动生成。然后订阅者可以直接从底层核心订阅队列接收消息。

所有这些都是在 STOMP 客户端的幕后完成的,但了解 STOMP 如何映射到 ActiveMQ Artemis 的地址模型很重要,这样您才能适当地配置东西


在您的情况下,您已经配置了一个具有 2 个 多播 队列的地址,并且您正在尝试使用这些队列。这个用例是点对点和 pub/sub 之间的混合,因为你有静态定义的队列(即不是代理为响应订阅者而自动创建的队列)但是队列是多播的。这些队列就像静态配置的持久订阅。要直接访问队列,您需要使用客户端的完全限定队列名称(即 FQQN)。 FQQN 遵循 <address>::<queue> 的模式,因此在您的情况下,您可以使用

Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic::Site.SOF.Order.Fulfillment.Submission.ActiveOmni.queue

Site.SOF.Order.Fulfillment.Submission.ActiveOmni.Topic::Site.SOF.Order.Fulfillment.Submission.ActiveOmni.log.queue