2015-06-16 22 views
1

我有一個關於使用spring-amqp通過XML接線和通過在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情況下是否存在某種我缺少的東西,或者這是否僅僅是不受支持。

我當然可以檢測到偵聽容器的故障並使用管理員重新聲明隊列,但是看到這對於XML有線示例來說不是必需的,我想知道我可能會丟失什麼。

使用org.springframework.amqp.spring兔1.4.5.RELEASE

回答

1

的管理員需要一個Spring應用上下文自動聲明的元素(隊列等)。

它向連接工廠註冊一個連接監聽器,並且當建立一個新的連接時,它會在應用上下文中查找所有的隊列等並註冊它們。

由於您使用的是「純」java(沒有Spring應用程序上下文),因此此機制無法工作。

您可以使用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); 

+0

感謝您的回覆,我現在明白了限制。這段代碼實際上是在Spring應用程序中運行的,但是我沒有在這裏使用上下文,因爲XML聲明不可能用於按照需要生成的這些隊列。我認爲我也可以在生成它們之後將這些隊列添加到現有的上下文中。也可以嘗試這種方法。謝謝。 –

+0

使用ConnectionListener重新聲明/重新綁定像魅力一樣工作的隊列,並且實現起來微不足道。非常感謝解決方案。 –