使用spring-amqp ListenerContainer关闭应用程序会挂起或花费很长时间

时间:2014-07-06 23:19:56

标签: java spring rabbitmq spring-amqp

我创造了一个简单的" Hello World"样式应用程序测试spring-amqp和RabbitMQ。使用ClassPathXmlApplicationContext从main函数加载Spring上下文,它启动amqp并设置一个ListenerContainer,用于侦听队列上的消息并在指定的pojo上调用指定的方法。一切正常,除了关闭应用程序。我在spring上下文中尝试了close()方法,它启动了ListenerContainer的关闭,它关闭了工作线程但是应用程序挂起而且它没有退出。我还在上下文中尝试了stop(),在ListenerContainer bean上尝试了shutdown()

问题: 如何干净地关闭具有spring-amqp ListenerContainers的spring上下文?

关机期间此处的日志输出:

Jul 07, 2014 1:00:22 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@472a2a50: startup date [Mon Jul 07 01:00:08 CEST 2014]; root of context hierarchy
Jul 07, 2014 1:00:22 AM org.springframework.context.support.DefaultLifecycleProcessor stop
INFO: Stopping beans in phase 2147483647
Jul 07, 2014 1:00:22 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Waiting for workers to finish.
Jul 07, 2014 1:00:23 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Successfully waited for workers to finish.

应用程序挂起并且在此输出后不会退出。

这是主要方法:

public static void main(String[] args) {
    final ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:app-config.xml");
    ctx.registerShutdownHook();
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println("Quitting from Main...");
            ctx.close();
        }
    }, 10000);
}

这是app-config.xml

<beans ...>
    <context:annotation-config />
    <import resource="amqp-config.xml" />
    <bean id="messageReceiver" class="com.knesek.amqp.spring.MessageReceiver" />
</beans>

与spring-amqp相关的配置(amqp-config.xml):

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
       xmlns="http://www.springframework.org/schema/rabbit" ...>

    <connection-factory id="connectionFactory" username="guest" password="guest" host="127.0.0.1"/>
    <template id="amqpTemplate" connection-factory="connectionFactory"/>
    <admin connection-factory="connectionFactory" />
    <direct-exchange name="incomingMessages">
        <bindings>
            <binding key="messages.inbound" queue="inboundMsgs"/>
        </bindings>
    </direct-exchange>
    <listener-container id="listenerContainer" connection-factory="connectionFactory"  >
        <listener ref="messageReceiver" method="receiveMessage" queues="inboundMsgs"  />
    </listener-container>
    <queue name="inboundMsgs"/>
</beans:beans>

1 个答案:

答案 0 :(得分:2)

听起来你有一些非守护程序线程可以保持你的上下文活着。关闭上下文应该停止任何框架线程。我建议你使用jstack / visualvm进行线程转储。