简体   繁体   中英

Customize the automatic reconnection settings to IBM MQ

I have written a code to connect to IBM MQ, and i am using ConnectionNameList which automatically reconnects to ibm mq.

I want to customize the reconnection which is happening implicitly. I have referred many articles on the inte.net but i am not able to figure it out.

This is my Queue Manager Config:

@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;
}


}

When i stop the queue manager, i get the following exceptions every 5 seconds:

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').

So i want that first 3 reconnection attempts should be a warn messages instead of error message as shown in above logs and 4th attempt onwards i want it to be an error message. and reconnection attempt to be every 10/15 seconds.

How do i configure these re-connection settings?

Any help would be greatly appreciated ! Thanks !

EDIT: I have added an exception listener as follows:

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("================================================");
                    
        }
            
    }
}

Now My logs are as follows:

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').

I dont want the default message listener container log to be printed onto console. how do we achieve that?

It says in IBM Docs :-

By default, the reconnection attempts happen at the following intervals:

  • The first attempt is made after an initial delay of 1 second, plus a random element up to 250 milliseconds.
  • The second attempt is made 2 seconds, plus a random interval of up to 500 milliseconds, after the first attempt fails.
  • The third attempt is made 4 seconds, plus a random interval of up to 1 second, after the second attempt fails.
  • The fourth attempt is made 8 seconds, plus a random interval of up to 2 seconds, after the third attempt fails.
  • The fifth attempt is made 16 seconds, plus a random interval of up to 4 seconds, after the fourth attempt fails.
  • The sixth attempt, and all subsequent attempts are made 25 seconds, plus a random interval of up to 6 seconds and 250 milliseconds after the previous attempt fails.

The reconnection attempts are delayed by intervals that are partly fixed and partly random. This is to prevent all of the IBM MQ classes for JMS applications that were connected to a queue manager that is no longer available from reconnecting simultaneously.

If you need to increase the default values, to more accurately reflect the amount of time that is required for a queue manager to recover, or a standby queue manager to become active, modify the ReconDelay attribute in the Channel stanza of the client configuration file.

You can read more about this attribute here .

Sounds like you need to put the following into your mqclient.ini file.

CHANNELS:
  ReconDelay=(10000,5000)

That is requesting a delay of 10 seconds plus a random element up to 5 seconds, which is my interpretation of your request for 10/15 seconds. You haven't asked for any of the reconnection attempts to be different in timing, although you can do this if you need to.

Note, it is not possible to change the WARN/ERROR status of the messages.

Remember that you can always turn off automatic reconnect and implement whatever you need yourself by catching the connection failures in your application. Automatic reconnect was designed for applications that were unable (or unwilling) to catch the connection failures.

I would add that the 5 second interval reconnect attempts are the DefaultMessageListenerContainer trying to reconnect. The default reconnect interval is 5 seconds - DEFAULT_RECOVERY_INTERVAL , so I'm not thinking that this involves the MQ reconnect mechanism.

With the exception handler listed above in place, you could programatically change the DefaultMessageListenerContainer setRecoveryInterval() or use setBackOff() to control the backoff interval.

As to disabling the logging, setting the log level for the DefaultMessageListenerContainer to FATAL should do it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM