Background

In many circumstances we experience queues loaded with messages are not dequeuing that fast due to various reasons. The deep queues often contribute to sluggish MQ performance. At times, we have no choice left but to disconnect the putter application or bring down the qmgr. All are certainly a costly affair on a production system. Standard exercises like slowing down the MQPUT or increase number of getter are the best practices. However, these are not always a feasible solution. It was always felt, if there was an option to redirect the message to a different queue to manage the load without restarting the qmgr or stopping the application, would have been useful. This article explains how we can accomplish using existing basic MQ features.

The design

Application (putter and getter) always connects to respective alias queue instead of a local queue. Once CURDEPTH rises abnormally we ALTER the alias queue referring to a different TARGET queue with a FORCE option. But this results the application to end with a reason code 2041′ i.e MQRC_OBJECT_CHANGED as the queue handle is invalidated by MQ. So consequently, if we absorb the return code in the application and issue a reopen then the new flow redirects this to the new local queue pointed by the alias queue.

Example of sequence

1. def qa(AQ) target(LQ1)
2. Application connects to AQ and start putting messages to LQ1 and when the CURDEPTH reaches very high
3. alter qa(AQ) TARGET(LQ2) force
4. The application must have a code snippet like:


While {
  ....
  MQPUT(.....) /* normal flow */

  if (Reason == MQRC_OBJECT_CHANGED)
  {
     MQCLOSE(.....)
     MQOPEN(.....)  /* Reopens and it is here it points to the new queue */
     MQPUT(.....)   /* for the last failed message */ 
     
     /* continue with the main loop */
  }
  .....
}


User can achieve greater degree of flexibility in a distributed queuing scenario having sender-receiver channel and remote queue. By changing the alias queue pointing to a different remote queue we can send messages to a range of local queues hosted by different qmgrs. We can apply the similar technique for a getter. In such case, checking for MQRC_OBJECT_CHANGED needs to be done after the MQGET call in the application.

Armed with the above technique we can write a script which monitors the CURDEPTH, performance event, network latency, server load etc. (or any business driven scenario like, time of the day) and switch the TARGET as needed. Applications without needing to know the actual queue can seamlessly put/get messages using array of queues.

Pictorial representation

This method gives a basic solution to the following:

a) Business driven flexible load balancing where we can have static definitions of various alternate routes to different destinations.
b) Event based routing where in a contingency on the fly definitions can be created and message can be sent on to the desired qmgr/queue.

This design is viable and effective only if we have

a) No message affinity between the consumer applications
b) Applications are using alias queue
c) MQRC_OBJECT_CHANGED is absorbed in the application


Moral of the story: The more you absorb the change, the more you tend to survive, here or somewhere!

2 comments on"A Basic Load balancing using MQ"

  1. This is a bad design. Asking the application to code for a pseudo clustering into the application is asking for problems. It is better to use MQ clustering. If you really want a light-weight clustering without using MQ clustering then I suggest you read this blog posting: https://www.capitalware.com/rl_blog/?p=3341 That solution does not require application code changes.

  2. Or just use MQ Clustering? Then no manual intervention is required.

Join The Discussion

Your email address will not be published.