2016-08-19 532 views
1

我寫了一個腳本,它使用Spring Rabbit將一些消息放在使用RabbitTemplate.convertAndSend的Rabbit隊列中,然後退出。但是,即使消息已入隊,Rabbit連接似乎仍可使應用程序保持活動狀態。我還沒有找到一種方式來清理告訴Rabbit服務器在消息排隊後停止。如何在Spring Rabbit中乾淨地關閉RabbitTemplate?

我已經能夠想到的最佳解決方案是將我的convertAndSend調用更改爲convertSendAndReceive,以便我知道消息已成功排隊,然後使用System.exit(0)退出。我切換到convertSendAndReceive,因爲它看起來convertAndSend發生在後臺線程或其他一些,因爲如果我做了一些這樣的調用後做一個System.exit(0),只有第一個這麼多的人會成功。

注意,僅僅創造了RabbitTemplate不會導致此行爲;通過其中一種「發送」方法使用它。

下面的代碼說明了問題。

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; 
import org.springframework.amqp.rabbit.connection.ConnectionFactory; 
import org.springframework.amqp.rabbit.core.RabbitTemplate; 

import static issues.RabbitSettings.*; //Static fields containing my test Rabbit connection info 

public class RabbitTemplateShutdownIssue { 
    public static void main(String[] args) { 
     RabbitTemplate rabbitTemplate = createRabbitTemplate(); 
     rabbitTemplate.convertAndSend(ROUTING_KEY, "Test"); // Or convertSendAndReceive 
     // The app never exits 
    } 

    private static RabbitTemplate createRabbitTemplate() { 
     RabbitTemplate rabbitTemplate = new RabbitTemplate(getConnectionFactory()); 
     rabbitTemplate.setExchange(EXCHANGE); 
     rabbitTemplate.setMandatory(true); 
     return rabbitTemplate; 
    } 

    private static ConnectionFactory getConnectionFactory() { 
     CachingConnectionFactory connectionFactory = new CachingConnectionFactory(HOSTNAME); 
     connectionFactory.setPublisherConfirms(true); 
     connectionFactory.setVirtualHost(VIRTUAL_HOST); 
     connectionFactory.setUsername(USERNAME); 
     connectionFactory.setPassword(PASSWORD); 
     return connectionFactory; 
    } 
} 

有沒有辦法告訴兔子客戶端關閉,理想情況下,所有消息已被列入隊列?

+0

**關閉彈簧**。你正在使用一個'ApplicationContext'的Spring Bean - 這是一個PITA來處理,因爲你需要按順序關閉這些東西,這樣你纔不會遇到異常。簡單的解決方案?正確地做! –

+0

@BoristheSpider在我的例子中沒有運行Spring容器,所以沒有Spring關閉。 –

+0

這完全是**我的觀點。 (我現在看到,我的意思是「沒有」而不是「與」) –

回答

3

如果你讓Spring管理豆,你可以當你完成close()應用程序上下文。

你現在配置(無Spring上下文),你可以調用連接工廠destroy(),一切都將關閉的方式。

使用對這樣的東西靜態方法是抗圖案;您需要將工廠存儲在靜態字段中,以便可以銷燬模板正在使用的那個。

你需要一個確認的回調來獲取兔收到發送確認。

+0

公平地說,實際的腳本是一個Groovy腳本,它執行一些基本的消息排隊然後退出,而不是一個完整的生產應用程序。我只是用靜態方法編寫了我的示例,因爲似乎使用Java比Spring更受Spring應用程序的支持。 –

+0

夠公平的。您需要在模板上進行確認回調才能確認兔子收到了發送。 –

+0

連接工廠的destroy()正是我所期待的。 –