【问题标题】:SpringJMS - How to Disconnect a MessageListenerContainerSpringJMS - 如何断开 MessageListenerContainer
【发布时间】:2018-06-26 09:23:21
【问题描述】:

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

环境 1. ActiveMQ 与 AMQP 2. SpringJMS 与 ApacheQpid

问题 调用destroy和stop方法后,队列中还有一个consumer。

所需解决方案

我想知道,如何干净地断开与队列的消费者连接为零的 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();
        }

    }

}

【问题讨论】:

    标签: spring jms activemq amqp spring-jms


    【解决方案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.
    

    如果您想要缓存连接,请使用 SingleConnectionFactory 或在 CCF 上调用 setCacheConsumers(false)

    【讨论】:

    • 我正在创建一个连接工厂并在两个或多个侦听器中使用它。这是一个不好的方法吗?我应该为每个消息侦听器容器使用一个连接工厂吗?
    • 没关系,但是CCF默认缓存消费者。最好将SingleConnectionFactory 用于侦听器容器。
    • 但是在这种情况下,您正在创建一个新的 CCF listenerContainer.setConnectionFactory(new CachingConnectionFactory(amqpConnectionFactory));。这是错误的。
    猜你喜欢
    • 2021-08-04
    • 2019-07-10
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多