繁体   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