我们正在尝试从 ActiveMQ 5.x 升级到最新的 Artemis (2.17),但我们的一个应用程序让我们感到悲伤。
该应用程序是一个使用 STOMP 的较旧的 PHP Web 应用程序。它创建一个临时响应队列,向目标发送消息,然后等待响应。在 ActiveMQ 5.x 下,这工作得很好(并且已经持续了很多年),但在 Artemis 中,请求只会挂起直到超时。
目标是基于 JMS API 和 Openwire 的 Java 应用程序。我们的大多数应用程序都是这样,相互通信没有问题......只有这个 PHP Web 应用程序有问题,而且它似乎是我们唯一基于 STOMP 的东西。
我们在启用 Artemis STOMP 调试的情况下单独运行单个事务,这是我们所看到的:
07:47:42,180 STOMP(/10.0.0.5:40618, f985f04d): IN << StompFrame[command=CONNECT, headers={login=<appid>, passcode=<app-password>}]
07:47:42,196 STOMP(/10.0.0.5:40618, f985f04d):OUT >> StompFrame[command=CONNECTED, headers={session=f985f04d}]
07:47:42,203 STOMP(/10.0.0.5:40618, f985f04d): IN << StompFrame[command=SUBSCRIBE, headers={ack=client, destination=/temp-queue/Reply-604379ee2f900, activemq.prefetchSize=1}]
07:47:42,235 STOMP(/10.0.0.5:40618, f985f04d): IN << StompFrame[command=SEND, headers={expires=1615035162000, destination=/queue/target, content-type=text/plain, reply-to=/temp-queue/Reply-604379ee2f900}, body=<--- message text---> body-bytes=[<--- message bytes --->, size=0]
07:48:42,247 STOMP(/10.0.0.5:40618, f985f04d): IN << StompFrame[command=DISCONNECT, headers={}]
问题的核心似乎是来自上面所示的“SEND”操作的消息永远不会到达接收者。我们已经验证接收器处于在线状态,并且它响应使用 JMS 和 Openwire 连接进行连接的其他客户端 - 但此 STOMP 消息不会路由到目的地。
如果我们关闭 Artemis 并恢复到 ActiveMQ 5.x,应用程序可以正常工作。
我们使用默认配置:
<acceptors>
<!-- useEpoll means: it will use Netty epoll if you are on a system (Linux) that supports it -->
<!-- amqpCredits: The number of credits sent to AMQP producers -->
<!-- amqpLowCredits: The server will send the # credits specified at amqpCredits at this low mark -->
<!-- amqpDuplicateDetection: If you are not using duplicate detection, set this to false
as duplicate detection requires applicationProperties to be parsed on the server. -->
<!-- amqpMinLargeMessageSize: Determines how many bytes are considered large, so we start using files to hold their data.
default: 102400, -1 would mean to disable large mesasge control -->
<!-- Note: If an acceptor needs to be compatible with HornetQ and/or Artemis 1.x clients add
"anycastPrefix=jms.queue.;multicastPrefix=jms.topic." to the acceptor url.
See https://issues.apache.org/jira/browse/ARTEMIS-1644 for more information. -->
<!-- Acceptor for every supported protocol -->
<acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true</acceptor>
<!-- AMQP Acceptor. Listens on default AMQP port for AMQP traffic.-->
<acceptor name="amqp">tcp://0.0.0.0:5672?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=AMQP;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpMinLargeMessageSize=102400;amqpDuplicateDetection=true</acceptor>
<!-- STOMP Acceptor. -->
<acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true</acceptor>
<!-- HornetQ Compatibility Acceptor. Enables HornetQ Core and STOMP for legacy HornetQ clients. -->
<acceptor name="hornetq">tcp://0.0.0.0:5445?anycastPrefix=jms.queue.;multicastPrefix=jms.topic.;protocols=HORNETQ,STOMP;useEpoll=true</acceptor>
<!-- MQTT Acceptor -->
<acceptor name="mqtt">tcp://0.0.0.0:1883?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=MQTT;useEpoll=true</acceptor>
</acceptors>
我们是否需要一些神奇的配置来将这些 STOMP 消息路由到正确的目的地?
第一个问题是消息发送到的
destination
。如 ActiveMQ Classic STOMP 文档 中所述,在 /queue/
框架的 SEND
标头上使用的 destination
前缀会自动删除。但是,在 ActiveMQ Artemis 中,这需要通过 ActiveMQ Artemis STOMP 文档中讨论的
anycastPrefix
参数显式配置,例如:
<acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true;anycastPrefix=/queue/;multicastPrefix=/topic/</acceptor>
为了完整性,还在这里配置了
multicastPrefix
。
配置完成后,您的消息将按预期发送至
target
。
但是,我认为
/temp-queue/
框架的 SUBSCRIBE
标头以及 destination
框架上的 reply-to
标头使用的 SEND
前缀仍然存在问题。 ActiveMQ Classic 也对这些进行了特殊处理(尽管我找不到任何有关它的文档)。 ActiveMQ Artemis 不会为这些创建临时资源,但我认为您仍然可以获得您想要的行为,因为代理可以自动创建和自动删除资源,就像它们是临时的一样。您需要在这里配置的主要内容是像以前一样的前缀,例如:
<acceptor name="stomp">tcp://0.0.0.0:61613?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;protocols=STOMP;useEpoll=true;anycastPrefix=/queue/,/temp-queue/;multicastPrefix=/topic/,/temp-topic/</acceptor>
由于您的 Stomp 客户端使用
reply-to
指定 /temp-queue/
标头,并且您的 OpenWire 客户端正在使用此标头,因此您还需要更改 OpenWire acceptor
,例如:
<acceptor name="artemis">tcp://0.0.0.0:61616?tcpSendBufferSize=1048576;tcpReceiveBufferSize=1048576;amqpMinLargeMessageSize=102400;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;amqpCredits=1000;amqpLowCredits=300;amqpDuplicateDetection=true;anycastPrefix=/temp-queue/;multicastPrefix=/temp-topic/</acceptor>
我已经打开了 ARTEMIS-3164 来实现用于识别 ActiveMQ Artemis 中的临时资源的前缀。