目標: 此次主要介紹jmsTemplate 連線MQ時發生錯誤時該如何處理
若要更多參數設定相關可以透過Containter
此Containter和我們一般使用docker不一樣
此範例由
- SpringBoot使用jms聆聽多個MQ(依據yml動態新增)
延伸
和上篇 7. SpringBoot使用jms 聆聽連線錯誤處理 一樣使用factory
但需要我們自行建制factory時就設定了 聆聽連線錯誤MQ的設定
透過之前建立factory的方法(DefaultJmsListenerContainerFactory) this.genJmsListenerContainerFactory(String concurrency,String receiveTimeout);
需要透過這個註冊方法configureJmsListeners(JmsListenerEndpointRegistrar registrar),使用registrar萃取出containter進行重新執行連線MQ
原先的設定
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
/*
* setConcurrency("1-3") is the same as
* setConcurrentConsumers(1);
* setMaxConcurrentConsumers(3);
* 設定初始和最大consumer大小
* */
factory.setConcurrency("1-3");
factory.setErrorHandler(jmsErrorHandler); // 同之前的錯誤處理
factory.setReceiveTimeout(-1);
retruen factory;
現在給這個factory定義唯一名稱在進行重新聆聽MQ
factoryId = "myFactory" + new Random().nextInt();
factory.setClientId(factoryId);
聆聽連線錯誤MQ
Thread.sleep(1000); // 每1000毫秒=1秒重新執行
count 外部宣告int 變數
factory.setExceptionListener(
exception -> {
log.error("\n*****start reconnect MQ*****");
try {
// 因為這部份是持續地回呼叫會有StackOverFlowError 堆疊過深的問題 因此每10次釋放一次資源釋放
if (NumberUtils.compare(10, count) == 0) {
log.info("====reconnected later====");
log.info("下一次顯示成功不為真");
count = 0;
} else {
Thread.sleep(1000);
// 如果 server log 顯示失敗 但預設重新連線MQ方式連上的話 則不會顯示連線成功
if (reconnection(registrar, factoryId, count++)) {
log.info("*****success connected MQ*****");
count = 0;
}
}
} catch (JMSException | InterruptedException e) {
e.printStackTrace();
}
}
);
reconnection(JmsListenerEndpointRegistrar registrar, String factoryId, int count){
for (MessageListenerContainer container : Objects.requireNonNull(registry.getEndpointRegistry()).getListenerContainers()) {
DefaultMessageListenerContainer defaultMessageListenerContainer=(DefaultMessageListenerContainer) container;
String regFactoryId = defaultMessageListenerContainer.getClientId();
if (StringUtils.equalsIgnoreCase(regFactoryId,factoryId)){
defaultMessageListenerContainer.start();
if (defaultMessageListenerContainer.isRunning() && NumberUtils.compare(1, initTime) == 0) {
String queueName = container.getDestinationName();
ConnectionFactory connectionFactory = container.getConnectionFactory();
String connName = StringUtils.EMPTY;
if (connectionFactory instanceof MQQueueConnectionFactory) {
MQQueueConnectionFactory mqQueueConnectionFactory = (MQQueueConnectionFactory)connectionFactory;
connName = mqQueueConnectionFactory.getConnectionNameList();
log.info("*****success connected MQ*****\nhost(prot): " + connName);
}
}
break;
}
}
缺點是有可能有時候顯示錯誤但事實上已經重新連線
因jmsTemplate有預設重新連線但不會顯示特定字串
不知有無特定介面可以實作
如過有知道的大神可以提供給我,非常感謝~
主要是給自己的一個紀錄,也分享給有需要的夥伴
註解部分有提及一些參考的連結,有興趣可以點進去看看喔
這是一個心血來潮,產生的文章
若有喜歡或交流的部分都歡迎在下方留言,多多關照。