7. SpringBoot使用jms 聆聽連線錯誤處理(2)


目標: 此次主要介紹jmsTemplate 連線MQ時發生錯誤時該如何處理
若要更多參數設定相關可以透過Containter
此Containter和我們一般使用docker不一樣

此範例由

  1. 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有預設重新連線但不會顯示特定字串
不知有無特定介面可以實作
如過有知道的大神可以提供給我,非常感謝~

主要是給自己的一個紀錄,也分享給有需要的夥伴
註解部分有提及一些參考的連結,有興趣可以點進去看看喔

這是一個心血來潮,產生的文章
若有喜歡或交流的部分都歡迎在下方留言,多多關照。

#mq #jmstemplate







你可能感興趣的文章

JQ總務處|點擊空白處關閉漢堡選單

JQ總務處|點擊空白處關閉漢堡選單

團隊的推進器 — 開放與學習

團隊的推進器 — 開放與學習

【JS幼幼班】Step.01 學習,從「不要害怕」開始

【JS幼幼班】Step.01 學習,從「不要害怕」開始






留言討論