如何修复ActiveMQ持久订阅引发“已使用持久消费者”错误

时间:2019-07-26 23:28:13

标签: java spring activemq

我正在尝试编写一个基本的ActiveMQ客户端来收听主题。我正在使用Spring Boot ActiveMQ。我有一个使用DefaultJmsListenerContainerFactory的各种教程构建的实现,但是在使它正常工作时遇到了一些问题。

@Configuration
@EnableJms
public class JmsConfig {
    @Bean
    public DefaultJmsListenerContainerFactory jmsContainerFactory(ConnectionFactory connectionFactory,
                                                                  DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConcurrency("3-10");
        factory.setConnectionFactory(connectionFactory);

        configurer.configure(factory, connectionFactory);

       factory.setSubscriptionDurable(true);
       factory.setClientId("someUniqueClientId");

       return factory;
   }
}

@JmsListener(destination="someTopic", containerFactory="jmsContainerFactory", subscription="someUniqueSubscription")
public void onMessage(String msg) {
    ...
}

一切正常,直到我尝试获得永久订阅为止。当我这样做时,我发现在容器工厂上设置了客户端ID时,出现了关于无法在共享连接上设置客户端ID的错误。

Cause: setClientID call not supported on proxy for shared Connection. Set the 'clientId' property on the SingleConnectionFactory instead.

当我更改代码以在连接工厂上设置客户端ID时(这是一个包装ActiveMQConnectionFactory的CachingConnectionFactory),该服务成功启动,读取了一些消息,然后开始一致地输出此错误:

Setup of JMS message listener invoker failed for destination 'someTopic' - trying to recover. Cause: Durable consumer is in use for client: someUniqueClientId and subscriptionName: someUniqueSubscription

我继续接收消息,但此错误也混在日志中。看来这可能是个问题,但是我真的不清楚如何解决。

我确实有一个幼稚的实现,没有任何弹簧代码,直接使用ActiveMQConnectionFactory,使用持久性使用者似乎很高兴(但它有自己的不同问题)。无论如何,我认为这并不缺乏对另一端持久连接的支持。

我希望在这一领域有更多经验的人可以帮助我弄清楚这个错误是我可以忽略的东西,还是解决该问题所需要做的事情。

谢谢!

1 个答案:

答案 0 :(得分:0)

JMS 1.1(由于使用的是ActiveMQ 5.x,因此正在使用)不支持共享的持久订阅。因此,当您使用setConcurrency("3-10")并且Spring尝试创建> 1个订阅时,您会收到一条错误消息。我看到解决此问题的两种主要方法:

  1. 使用setConcurrency("1")会将订阅者/消费者的数量限制为1。根据您的要求,这可能会对性能产生严重的负面影响。
  2. 切换到{em> 支持JMS 2.0的ActiveMQ Artemis并调用setSubscriptionShared(true)