Act on MQ Event messages

Some event messages tell you something that you might like to act upon immediately. Others you might just want to keep an eye on, for example channel problems where channel retry will probably cover it.

In this blog post, I’ll demonstrate an example of how you might use MQEV to immediately act upon an event message. In our demonstration today, we have a cluster of queue managers with a number of hosted queues called CLUS.Q1. Using a similar tactic to that used by the The Cluster Queue Monitoring sample program (AMQSCLM), we’re going to lower the CLWLPRTY value of a cluster queue when it becomes a less useful choice, in this case when it hits the Queue-High state.

Turning on Queue Depth Events in IBM MQ

On each cluster queue manager, we would turn on Queue Depth events with the following commands, and set an initial value of CLWLPRTY to allow it to be lowered.

ALTER QMGR PERFMEV(ENABLED)

ALTER QLOCAL(CLUS.Q1) MAXDEPTH(10000) +
      QDEPTHHI(40) QDEPTHLO(10) +
      QDPHIEV(ENABLED) +
      CLWLPRTY(5)
Explanation of Queue Depth settings

In this example, rather than following the usual Queue Depth High of 80% and Queue Depth Low of 20%, with, say a maximum depth of 5000, I’ve doubled the maximum depth to 10000, and set the percentages so I still get a Queue High at 4000, and Queue Low at 1000. This gives me much more head-room before I hit Queue Full, but with 4000 messages on the queue, that’s still a hefty backlog to work through.

Turning on Queue Depth Events in MQEV

To ensure MQEV is processing performance events, issue the following command to MQEV.

RESUME EVQ(SYSTEM.ADMIN.PERFM.EVENT)

Processing Queue Depth Events in MQEV

Now we’re going to add some instructions to MQEV, to tell it what do to when it receives Queue Depth events. This is done by using the MQEVEvent() function in the mqev.mqx script. In the script below it tests for the event type, looking for performance events (event.evtype = PERFM), and then displays the queue that the event was all about, since we need to tell whether it was a cluster queue, and if so what it currently has as a value for CLWLPRTY.

*********************************************************************
* Function for processing an event                                  *
*********************************************************************
func MQEVEvent()
  if (event.evtype = PERFM)
    =mqsc
    @qname = event.evoobjname
    DISPLAY QLOCAL(<@qname>) ALL
    if (CLUSTER OR CLUSNL)
      ...
    endif
  endif
  endfunc

If it finds that this is indeed a cluster queue, then it will do some adjusting of the CLWLPRTY value based on whether this is Queue High, Queue Low, or Queue Full.

If you have a good naming convention for your queues, you could avoid the step of displaying the queue, and rely on your naming convention pattern to inform you that it is a cluster queue.

*********************************************************************
* Function for processing an event                                  *
*********************************************************************
func MQEVEvent()
  if (event.evtype = PERFM)
    =mqsc
    @qname = event.evoobjname
    DISPLAY QLOCAL(<@qname>) ALL
    if (CLUSTER OR CLUSNL)
      if (event.evreason = PERQDPHI)
        ALTER QLOCAL(<@qname>) CLWLPRTY(4)
      endif
      if (event.evreason = PERQDPFULL)
        ALTER QLOCAL(<@qname>) PUT(DISABLED)
      endif
      if (event.evreason = PERQDPLO)
        ALTER QLOCAL(<@qname>) CLWLPRTY(5) PUT(ENABLED)
      endif
    endif
  endif
endfunc

When it hits a Queue High state, it lowers the CLWLPRTY by one, making it a less good choice than instances of the queue on other queue managers. Of course, if all instances of the queue are lowered in the same way, they all become equally appropriate choices again. You might, in addition, want to raise an alert to ensure the MQ System administrator is aware of the situation.

When it hits a Queue Full state, it changes the queue to be PUT(DISABLED). This is because that attribute is one of the ones flowed round the cluster, and it will stop this queue from being chosen as a result.

When it hits a Queue Low state, it sets the CLWLPRTY back to 5 and re-enables the queue for putting again.

These are just example actions to show you how you could act upon an event message at the moment it arrives on the event queue. You can of course, issue any command you like. You could for example, start more instances of your application, perhaps by running a script using the MQSCX system() function, or by defining it as an MQ SERVICE object and starting that.


Read more about MQEV, and download a copy, from the MQEV Web Page. If you don’t have a licence and would like to try out MQEV before deciding whether to buy then send an email to support@mqgem.com and a 1-month trial licence will be sent to you.

The team at MQGem would love to hear what you think. Leave your comments here.

This site uses Akismet to reduce spam. Learn how your comment data is processed.