簡體   English   中英

自定義與 IBM MQ 的自動重新連接設置

[英]Customize the automatic reconnection settings to IBM MQ

我已經編寫了連接到 IBM MQ 的代碼,並且我正在使用自動重新連接到 ibm mq 的 ConnectionNameList。

我想自定義隱式發生的重新連接。 我在 inte.net 上提到了很多文章,但我無法弄明白。

這是我的隊列管理器配置:

@Configuration
public class QM1Config{
    

    public String queueManager;
    public String queue;
    public String channel;
    public String connName;
    public String user;
    public String password;
    private static final int RECONNECT_TIMEOUT = 10;
    
    @Autowired
    MQService config;
    

@Bean
public MQConnectionFactory mqQueueConnectionFactory() {
    this.channel = config.getHosts().get(0).getChannel();
    this.user = config.getHosts().get(0).getUser();
    this.password = config.getHosts().get(0).getPassword();
    this.queueManager = config.getHosts().get(0).getQueueManager();
    this.queue = config.getHosts().get(0).getQueue();
    this.connName = config.getHosts().get(0).getConnName();
    System.out.println(channel+" "+connName+" "+queueManager+" "+user);
    MQConnectionFactory mqQueueConnectionFactory = new MQConnectionFactory();
    try {
        mqQueueConnectionFactory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
        mqQueueConnectionFactory.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, false);
        mqQueueConnectionFactory.setCCSID(1208);
        mqQueueConnectionFactory.setChannel(channel);
        mqQueueConnectionFactory.setStringProperty(WMQConstants.USERID, user);
        mqQueueConnectionFactory.setStringProperty(WMQConstants.PASSWORD, password);
        mqQueueConnectionFactory.setQueueManager(queueManager);
        mqQueueConnectionFactory.setConnectionNameList(connName);
    } catch (Exception e) {
        e.printStackTrace();
        
        
    }
    return mqQueueConnectionFactory;
 
}


@Bean
public JmsListenerContainerFactory<?> qm1JmsListenerContainerFactory(@Qualifier("mqQueueConnectionFactory") MQConnectionFactory mqQueueConnectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) throws InterruptedException {
  DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
  this.queue = config.getHosts().get(0).getQueue();
  configurer.configure(factory, mqQueueConnectionFactory);
  return factory;
}

@Bean("jmsTemplate1")
public JmsTemplate jmsTemplate(@Qualifier("mqQueueConnectionFactory") MQConnectionFactory mqQueueConnectionFactory) {
    JmsTemplate jmsTemplate1  = new JmsTemplate(mqQueueConnectionFactory);
    return jmsTemplate1;
}


}

當我停止隊列管理器時,每 5 秒就會出現以下異常:

2022-04-24 01:17:43.194  WARN 6644 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Setup of JMS message listener invoker failed for destination 'Q5' - trying to recover. Cause: JMSWMQ2002: Failed to get a message from destination 'Q5'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
2022-04-24 01:17:43.232 ERROR 6644 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Could not refresh JMS Connection for destination 'Q5' - retrying using FixedBackOff{interval=5000, currentAttempts=0, maxAttempts=unlimited}. Cause: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2059' ('MQRC_Q_MGR_NOT_AVAILABLE').
2022-04-24 01:17:48.243 ERROR 6644 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Could not refresh JMS Connection for destination 'Q5' - retrying using FixedBackOff{interval=5000, currentAttempts=1, maxAttempts=unlimited}. Cause: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE').
2022-04-24 01:17:53.245 ERROR 6644 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Could not refresh JMS Connection for destination 'Q5' - retrying using FixedBackOff{interval=5000, currentAttempts=2, maxAttempts=unlimited}. Cause: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE').
2022-04-24 01:17:58.250 ERROR 6644 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Could not refresh JMS Connection for destination 'Q5' - retrying using FixedBackOff{interval=5000, currentAttempts=3, maxAttempts=unlimited}. Cause: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE').

所以我希望前 3 次重新連接嘗試應該是一條警告消息,而不是上面日志中所示的錯誤消息,而從第 4 次嘗試開始,我希望它是一條錯誤消息。 並嘗試每 10/15 秒重新連接一次。

如何配置這些重新連接設置?

任何幫助將不勝感激 ! 謝謝 !

編輯:我添加了一個異常偵聽器,如下所示:

public class MQExceptionListener implements ExceptionListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(MQExceptionListener.class);

    int count = -1;
    

    @Override
    public void onException(JMSException ex) {
        
        if(count > 2) {
            System.out.println("COUNT - "+ count);
            count++;
                     LOGGER.error("***********************************************");
                        LOGGER.error(ex.toString()+" THIS IS EX TO STRING");
                        if (ex.getLinkedException() != null) {
                            LOGGER.error(ex.getLinkedException().toString()+" THIS IS getLinkedException TO STRING");
                        }
                        LOGGER.error("================================================");

        }else {
            System.out.println("COUNT - "+ count);
            count++;
                     LOGGER.warn("***********************************************");
                        LOGGER.warn(ex.toString()+" THIS IS EX TO STRING");
                        if (ex.getLinkedException() != null) {
                            LOGGER.warn(ex.getLinkedException().toString()+" THIS IS getLinkedException TO STRING");
                        }
                        LOGGER.warn("================================================");
                    
        }
            
    }
}

現在我的日志如下:

COUNT - 1
2022-04-24 14:41:04.905  WARN 9268 --- [enerContainer-1] com.mq.sslMQ.MQExceptionListener         : ***********************************************
2022-04-24 14:41:04.905  WARN 9268 --- [enerContainer-1] com.mq.sslMQ.MQExceptionListener         : com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.
Check the queue manager is started and if running in client mode, check there is a listener running. Please see the linked exception for more information. THIS IS EX TO STRING
2022-04-24 14:41:04.905  WARN 9268 --- [enerContainer-1] com.mq.sslMQ.MQExceptionListener         : com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE'). THIS IS getLinkedException TO STRING
2022-04-24 14:41:04.905  WARN 9268 --- [enerContainer-1] com.mq.sslMQ.MQExceptionListener         : ================================================
2022-04-24 14:41:04.905 ERROR 9268 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer  : Could not refresh JMS Connection for destination 'Q5' - retrying using FixedBackOff{interval=5000, currentAttempts=1, maxAttempts=unlimited}. Cause: JMSWMQ0018: Failed to connect to queue manager 'QM5' with connection mode 'Client' and host name 'Client'.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2538' ('MQRC_HOST_NOT_AVAILABLE').

我不希望將默認消息偵聽器容器日志打印到控制台上。 我們如何做到這一點?

它在IBM 文檔中說:-

默認情況下,重新連接嘗試按以下時間間隔進行:

  • 第一次嘗試是在 1 秒的初始延遲后進行的,加上一個長達 250 毫秒的隨機元素。
  • 在第一次嘗試失敗后,第二次嘗試將在 2 秒內加上最多 500 毫秒的隨機間隔。
  • 第三次嘗試在 4 秒內進行,在第二次嘗試失敗后加上最多 1 秒的隨機間隔。
  • 在第三次嘗試失敗后,第四次嘗試的時間為 8 秒,外加最多 2 秒的隨機間隔。
  • 第 5 次嘗試在 16 秒內進行,在第 4 次嘗試失敗后加上最多 4 秒的隨機間隔。
  • 第六次嘗試和所有后續嘗試都在 25 秒內進行,加上前一次嘗試失敗后最多 6 秒和 250 毫秒的隨機間隔。

重新連接嘗試被部分固定和部分隨機的時間間隔延遲。 這是為了防止所有連接到不再可用的隊列管理器的 JMS 應用程序的 IBM MQ 類同時重新連接。

如果您需要增加默認值,以更准確地反映隊列管理器恢復或備用隊列管理器變為活動所需的時間量,請修改客戶端配置文件的 Channel 節中的 ReconDelay 屬性。

您可以在此處閱讀有關此屬性的更多信息。

聽起來您需要將以下內容放入您的mqclient.ini文件中。

CHANNELS:
  ReconDelay=(10000,5000)

那就是要求延遲 10 秒加上一個最多 5 秒的隨機元素,這是我對你要求 10/15 秒的解釋。 您沒有要求任何重新連接嘗試在時間上有所不同,但如果需要,您可以這樣做。

請注意,無法更改消息的 WARN/ERROR 狀態。

請記住,您始終可以關閉自動重新連接並通過捕獲應用程序中的連接失敗來實現您需要的任何內容。 自動重新連接專為無法(或不願意)捕獲連接失敗的應用程序而設計。

我要補充一點,5 秒間隔重新連接嘗試是DefaultMessageListenerContainer嘗試重新連接。 默認重新連接間隔為 5 秒 - DEFAULT_RECOVERY_INTERVAL ,所以我認為這不涉及 MQ 重新連接機制。

使用上面列出的異常處理程序,您可以通過編程更改DefaultMessageListenerContainer setRecoveryInterval()或使用setBackOff()來控制退避間隔。

至於禁用日志記錄,將DefaultMessageListenerContainer的日志級別設置為 FATAL 應該可以做到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM