虚拟主题在使用 ActiveMQ 5.x 的连接工厂时有效,但在 Artemis 的连接工厂中无效

Virtual topics work when using ActiveMQ 5.x's connection factory, but not Artemis' connection factory

我正在将现有代码从使用 ActiveMQ 5.x 迁移到使用 Artemis。使用 org.apache.activemq.ActiveMQConnectionFactory 时,我的虚拟主题消费者队列中有发送到虚拟主题的消息排队给它们。使用 org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory 时,它们不会。

使用 ActiveMQ 5.x 的连接工厂为虚拟主题工作的连接池配置是:

<bean id="jmsFactory" class="org.apache.activemq.jms.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
    <property name="connectionFactory">
        <bean class="org.apache.activemq.ActiveMQConnectionFactory">
            <property name="brokerURL" value="failover:${activemq.broker}" />
            <property name="userName"  value="${activemq.credentials.username}"/>
            <property name="password"  value="${activemq.credentials.password}"/>
        </bean>
    </property>
    <property name="maxConnections"                    value="${activemq.connectionPool.size}" />
    <property name="maximumActiveSessionPerConnection" value="${activemq.connectionPool.sessionsPerConnection}" />
</bean>

不能使用 Artemis 连接工厂的虚拟主题的连接池配置是:

<bean id="jmsConnectionFactory" class="org.apache.activemq.jms.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
    <property name="connectionFactory">
        <bean class="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory">
            <constructor-arg name="url"      value="${activemq.broker}"/>
            <constructor-arg name="user"     value="${activemq.credentials.username}"/>
            <constructor-arg name="password" value="${activemq.credentials.password}"/>
        </bean>
    </property>
    <property name="maxConnections"                    value="${activemq.connectionPool.size}" />
    <property name="maximumActiveSessionPerConnection" value="${activemq.connectionPool.sessionsPerConnection}" />
</bean>

对于虚拟话题,我的消费者是Camel路由,生产者是Spring的JmsTemplateclass的实例。生产者被配置为生产模式 VirtualTopic.Foo 中的主题,消费者被配置为从模式 jms:queue:VirtualTopic.Foo::Consumer.MyApplication.VirtualTopic.Foo 中的 Camel 端点消费。 jms Camel 组件配置了上面的 jmsFactory bean,JmsTemplate 实例也是如此:

<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
    <property name="connectionFactory"  ref="jmsFactory"/>
    <property name="deliveryPersistent" value="${activemq.delivery.persistent}"/>
</bean>

理想情况下,我可以使用 Artemis 的 ActiveMQConnectionFactory。是什么导致发送到虚拟主题的消息在使用时没有被分派到消费者队列?

这可能与所使用的 JMS 驱动程序有关,也可能无关。如何以及何时创建虚拟主题及其消费者似乎是一个问题。下面详细介绍了我是如何实现这一目标的,但简而言之,请确保在创建消费者之前创建虚拟主题。


我注意到我的一个虚拟主题 VirtualTopic.Fig 正在运行,但我的其他虚拟主题 none 正在运行。虚拟主题的所有消费者队列都是使用完全限定的队列名称创建的,如 Artemis documentation 中所述(订阅队列 VirtualTopic.Fig::Consumer.A.VirtualTopic.Fig 而不是 Consumer.A.VirtualTopic.Fig)。我 运行 listAddresses 管理命令并看到虚拟主题的输出:

name                        size    consumers      anycast    multicast 
-----------------------------------------------------------------------
VirtualTopic.Apple             -            1            Y            -
VirtualTopic.Banana            -            1            Y            -
VirtualTopic.Cantaloupe        -            1            Y            -
VirtualTopic.DragonFruit       -            1            Y            -
VirtualTopic.ElderBerry        -            1            Y            -
VirtualTopic.Fig               -            1            Y            Y
-----------------------------------------------------------------------

使用 updateAddress 命令 (updateAddress VirtualTopic.DragonFruit ANYCAST,MULTICAST),我更新了 VirtualTopic.DragonFruit 以具有多播路由,重新启动了我的消费者,其中大部分开始接收消息。假设剩下的消费者没有工作,因为它们是在创建主题之前创建的,并且绑定到地址的任播版本,对于每个地址,我:

  1. 关闭所有从虚拟主题生成或使用的应用程序。
  2. 使用 destroyQueue 命令 (destroyQueue Consumer.A.VirtualTopic.DragonFruit true true) 销毁了消费者队列。
  3. 使用 deleteAddress 命令 (deleteAddress VirtualTopic.DragonFruit) 删除了主题。
  4. 使用 createAddress 命令 (createAddress VirtualTopic.DragonFruit MULTICAST) 将主题创建为多播地址。
  5. 再次启动所有应用程序。

手动创建虚拟主题后,一切开始工作。 listAddresses 命令的新输出是:

name                        size    consumers      anycast    multicast 
-----------------------------------------------------------------------
VirtualTopic.Apple             -            1            -            Y
VirtualTopic.Banana            -            1            -            Y
VirtualTopic.Cantaloupe        -            1            -            Y
VirtualTopic.DragonFruit       -            1            -            Y
VirtualTopic.ElderBerry        -            1            -            Y
VirtualTopic.Fig               -            1            -            Y
-----------------------------------------------------------------------

并且 listQueues 命令的输出显示消费者现在正在接收消息:

name                                   size    consumers     enqueued     dequeued 
----------------------------------------------------------------------------------
Consumer.A.VirtualTopic.Apple             0            1           88           88
Consumer.A.VirtualTopic.Banana            0            1            4            4
Consumer.A.VirtualTopic.Cantaloupe        0            1           12           12
Consumer.A.VirtualTopic.DragonFruit       0            1           74           74
Consumer.A.VirtualTopic.ElderBerry        0            1         1776         1776
Consumer.A.VirtualTopic.Fig               0            1           75           75
----------------------------------------------------------------------------------