经纪人中断后未重新创建自动删除队列

时间:2015-06-16 13:22:51

标签: spring-amqp

我有一个关于通过XML连接使用spring-amqp以及通过在java代码中创建各种对象的问题。

通过XML和Java代码执行此操作非常简单,并且在大多数情况下一直很适合我。但是,在经纪人中断后(通过关闭并重新启动我的经纪人进行模拟),我得到了两个不同的结果。

使用XML连接创建spring-amqp对象时,一切正常。重新建立连接,重新创建队列并重新开始接收消息。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:ctx="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:rabbit="http://www.springframework.org/schema/rabbit"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
                        http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.4.xsd">

    <rabbit:connection-factory id="connectionFactory" 
        addresses="192.168.1.10:5672" 
        username="guest" 
        password="guest" 
    />

    <rabbit:admin connection-factory="connectionFactory"/> 

    <rabbit:queue name="testQueue" id="testQueue" auto-declare="true" auto-delete="true" exclusive="false"/>

    <rabbit:fanout-exchange name="testExchange" id="testExchange" >
        <rabbit:bindings>
            <rabbit:binding queue="testQueue" />
        </rabbit:bindings>
    </rabbit:fanout-exchange>

    <bean class="TestConsumer" id="testConsumer" />

    <rabbit:listener-container connection-factory="connectionFactory">
        <rabbit:listener queues="testQueue" ref="testConsumer" method="inbound" />
    </rabbit:listener-container>

</beans>

但是,当使用Java创建spring-amqp对象时,我遇到了问题。重新建立连接,但是我立即点击报告未找到队列的异常。管理员不会尝试重新创建队列,在几个例外之后,侦听器容器就会停止。

public static void main(String[] args) {

    CachingConnectionFactory cf = new CachingConnectionFactory("192.168.1.10", 5672);

    RabbitAdmin admin = new RabbitAdmin(cf);

    FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
    admin.declareExchange(testExchange);

    Queue testQueue = new Queue("testQueue", true, false, true);
    admin.declareQueue(testQueue);

    admin.declareBinding(BindingBuilder.bind(testQueue).to(testExchange));

    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(cf);
    container.setRabbitAdmin(admin);

    container.setQueues(testQueue);
    container.setMessageListener(new MessageListenerAdapter() {
        public void handleMessage(String text) {
            System.out.println("Received : " + text);
        }
    });
    container.afterPropertiesSet();

    container.start();

    try {
        Thread.sleep(600000L);
    } catch(Exception e) {
        e.printStackTrace();
    }

    container.stop();
    container.destroy();

    System.out.println("Exiting");
}

这是我在重新建立连接之后和侦听器容器退出之前看到的(三次或四次)异常:

Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'testQueue' in vhost '/', class-id=50, method-id=10)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:478)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:315)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:144)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:91)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:552)

我认为XML布线案例和纯Java案例应该等效,但显然情况并非如此。我不确定是否  我的Java案例中缺少某些内容,或者是否仅支持此内容。

我当然可以检测到侦听器容器的失败,并使用admin重新声明队列,但是因为这不是必需的XML有线示例,我想知道我可能会遗漏什么。

使用org.springframework.amqp.spring-rabbit 1.4.5.RELEASE

1 个答案:

答案 0 :(得分:1)

管理员需要一个Spring Application Context来自动声明元素(队列等)。

它在连接工厂中注册连接侦听器,并且在建立新连接时,它会在应用程序上下文中查找所有队列等并注册它们。

因为你正在使用&#34; pure&#34; java(没有Spring Application Context),这种机制无法工作。

您可以使用Spring Java Configuration替换XML(使用@Bean定义),或者您必须使用连接工厂注册自己的类来执行声明。

请参阅管理源代码for how he registers the listenerinitialize method了解他如何进行声明。

你只需要做你的

FanoutExchange testExchange = new FanoutExchange("testExchange", true, false);
admin.declareExchange(testExchange);

Queue testQueue = new Queue("testQueue", true, false, true);
admin.declareQueue(testQueue);

在听众中。