SpringJMS - 如何断开MessageListenerContainer

时间:2018-01-17 13:15:21

标签: spring jms activemq amqp spring-jms

我想断开队列的DefaultMessageListenerContainer。我正在使用dmlc.stop(),dmlc.shutdown()。在连接时,5个消费者线程连接到队列。当我尝试断开连接时,4个消费者断开连接,但有1个消费者保持连接状态。 (见线程末尾的截图)。

环境 1.带AMQP的ActiveMQ 2.使用ApacheQpid的SpringJMS

问题 在调用destroy和stop方法之后,仍然有一个消费者连接到队列。

必备解决方案

我想知道,如何干净地断开MessageListenerContainer与队列的零消费者连接。

配置和代码

    @Bean
public DefaultMessageListenerContainer getMessageContainer(ConnectionFactory amqpConnectionFactory, QpidConsumer messageConsumer){
    DefaultMessageListenerContainer listenerContainer = new DefaultMessageListenerContainer();
    listenerContainer.setConcurrency("5-20");
    listenerContainer.setRecoveryInterval(jmsRecInterval);
    listenerContainer.setConnectionFactory(new CachingConnectionFactory(amqpConnectionFactory));
    listenerContainer.setMessageListener(messageConsumer);
    listenerContainer.setDestinationName(destinationName);
    return listenerContainer;
}

private void stopListenerIfRunning() {
        DefaultMessageListenerContainer dmlc = (DefaultMessageListenerContainer) ctx.getBean("messageContainer");
        if (null != dmlc) {
            if(!dmlc.isRunning()){return;}
            dmlc.stop(new Runnable() {
                @Override
                public void run() {
                    logger.debug("Closed Listener Container for Connection {}", sub.getQueueName());
                    if (sub.getSubscriptionStatus() == SubscriptionStatus.DELETED
                            || sub.getSubscriptionStatus() == SubscriptionStatus.SUSPENDED_DELETE) {
                        listenerHandles.remove(sub.getQueueName());
                    }
                }
            });
            dmlc.destroy();
            dmlc.shutdown();
        }

    }

}

enter image description here

1 个答案:

答案 0 :(得分:1)

  

listenerContainer.setConnectionFactory(newCachingConnectionFactory(amqpConnectionFactory));

您需要销毁CachingConnectionFactory

由于会话是长期存在的,因此您通常不需要使用侦听器容器的缓存工厂;如果你有可变并发,你肯定不应该;来自javadocs ......

 * <p><b>Note: Don't use Spring's {@link org.springframework.jms.connection.CachingConnectionFactory}
 * in combination with dynamic scaling.</b> Ideally, don't use it with a message
 * listener container at all, since it is generally preferable to let the
 * listener container itself handle appropriate caching within its lifecycle.
 * Also, stopping and restarting a listener container will only work with an
 * independent, locally cached Connection - not with an externally cached one.

如果您希望缓存连接,请在CCF上使用SingleConnectionFactory或致电setCacheConsumers(false)