ApacheMQ Artemis 保留没有路由的消息

ApacheMQ Artemis keep messages with no route

我只使用 Artemis 2.6.2 和 STOMP 以及以下星座:

经纪人:

服务器:

客户端 123:

当我在 Artemis Console 观看时,会发生以下情况:

  1. 没有连接服务器和客户端:没有地址或 queue 存在

  2. 服务器连接:Artemis 创建多播地址 TaskResponse 并为此地址创建多播 queue,过滤器为空

  3. 客户端 123 连接:Artemis 创建多播地址 TaskRequest 并为此地址创建多播 queue,过滤器 clientId = 123

  4. 消息交换:消息按预期从服务器传输到客户端并返回服务器。

  5. 客户端 123 断开连接:Artemis 删除多播地址 TaskRequest 和对应的多播 queue,过滤器 clientId = 123

  6. 服务器向客户端 123 的 TaskRequest 发送消息:根据服务器上的 STOMP 客户端消息发送成功。在代理上,消息消失了。

  7. 反之亦然:客户端 123 已连接,服务器未连接:根据客户端 123 上的 STOMP 客户端,消息发送成功。在代理上,消息消失了。

我的猜测是消息被丢弃是因为没有到订阅者的路由。如果我在 broker.xml 的 address-settings 部分启用选项 "send-to-dla-on-no-route",消息将直接转到死信 queue.

您知道在订阅者重新连接之前保留消息的方法吗?

附录 1:STOMP 消息

我正在使用 Stomp.Net Library with SelectorsCore Example 但仅减少到选择器 s1。工作流程和我上面写的有点不同。

不幸的是,我没有找到启用将 STOMP 消息记录到 Artemis 文件中的示例。因此,我用 WireShark, exported as text and uploaded into Gist StompMessages.txt 记录了数据包。您可以在那里看到不同的 STOMP 消息,例如搜索 CONNECT、SEND 等

解决方案

解决方案是在 broker.xml 中的 acceptor 元素中使用选项 anycastPrefix=/queue/ 强制 queue 键入 ANYCAST:

<acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true;anycastPrefix=/queue/</acceptor>

您观察到的是预期的行为。如果您将消息发送到没有队列的地址(或者在 STOMP 术语中 - 没有订阅者的目的地),那么该消息将无处可去并被丢弃。这是正常的 pub/sub 语义。

如果您想在没有订阅者的情况下保留消息,您可以:

  1. 使用任播(即点对点)语义而不是多播。 Artemis documentation.
  2. 中对此进行了讨论
  3. 使用 "durable" STOMP 订阅者,如 Artemis documentation 中所述。这里需要注意的是,在发送消息之前仍然需要创建订阅,并且您还需要确保在完成订阅后删除订阅,否则它可能会累积消息。