Not all messages which are placed on a queue are guaranteed to be processed.
Something might go wrong while messages are picked up from the queue by listener
programs. For example, consider a scenario when a badly formatted message is
dropped on a queue; the application program may not be able to process such a
message. The program which de-queues the message backs out the message receipt
and places the message back on the queue. Such messages are called poison
messages. As the name suggests, a poison message indicates some payload
malformation. Furthermore, poison messages may cause deadlocks and badly impact
the application performance. If a poison message is not removed from the queue,
the receiving application can get stuck in an infinite loop. WebSpehere MQ
provides nifty techniques to handle such poison messages. MQ can re-queue the
poison messages on a separate queue (called backout queue) which can be later
debugged and cleared. In this article, we'll demonstrate the configuration
modifications required for WebSpehere MQ to deal with poison messages and walk
through with an application code which shall demonstrate message backout and
redelivery.
Direct Hit! |
Applies To: SOA Developers USP: Improve application performance by backing out poison messages Primary Link: http://www.ibm.com/software/integration/wmq Keywords: WebSphere MQ |
Configuring MQ backout queue
As discussed, a backout queue is a special type of local queue object which is
intended to store poison messages. To begin with, we'll create a local queue
named inbound.alerts and a backout queue called failed.payload. The MQ Script
Commands (MQSC) required to create the local and backout queue are depicted in
figure.
Notice carefully that the runmqsc script command is executed without
specifying any queue manager name. WebSphere MQ will choose the default queue
manager object- PCQuest. All MQ script commands are then run against the PCQuest
queue manager object. We begin by defining two local queues- inbound.alerts and
failed.payload. The ALTER QLOCAL script command is then issued to alter
properties of the inbound.alerts queue to designate failed.payload as a backout
queue.
After running the above mentioned MQ script commands, we'll have the two
local queue objects defined and configured. The WebSphere MQ explorer view ID is
shown in the figure.
As an administrator, you can configure MQSC commands for creating the backout queue. |
Notice that MQ doesn't use any special icon for the backout queue. It's just
like any ordinary local queue object. To validate the MQSC commands you can also
review the properties of the inbound.alerts queue object, as shown in the figure
Backing out poison messages
For the sake of demonstration, we'll present a code snippet to describe the
backout operation and then move the poison message (assuming that the backout
counter has reached the threshold value) to the backout queue object.
After running the MQ script commands, we'll have the local queue objects defined and configured. |
while (true) {
myMessage.clearMessage();
myMessage.correlationId = MQC.MQCI_NONE;
myMessage.messageId = MQC.MQMI_NONE;
myQueue.get(myMessage, gmo);
//check for the threshold counter
if (myMessage.backoutCount <= boThresh) {
System.out.println("BackoutCount: "
+ myMessage.backoutCount + " of " + boThresh); /*
* increase backout count by one and put the message back on the queue */
qMgr.backout();
} else {
System.out.println ("Message is poison, moving to "+ backoutQueueName);
int openPutOptions = MQC.MQOO_
OUTPUT+ MQC.MQOO_FAIL_ IF_QUIESCING
+ MQC.MQOO_PASS _ALL_CONTEXT;
MQQueue myPutQueue = qMgr.accessQueue (backoutQueueName, openPutOptions, null,
null, null);
MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options = pmo.options | MQC.MQPMO_SYNCPOINT | MQC.MQPMO _PASS_ALL_CONTEXT;
pmo.contextReference = myQueue;
myPutQueue.put(myMessage, pmo);
/* * close the current transaction and release message(s) held by the syncpoint
control */
qMgr.commit();
myPutQueue.close();
break; }}
The program opens the alerts.inbound queue to inquire the backout queue name
and the threshold value. The message retrieval operation is wrapped in a
transaction. This is done to avoid reading the messages in destructive mode. The
program gets the first message on the queue and then backs it out until the
backout threshold is reached. The program output is shown in the figure.
These are the Local queue properties. Note that the default threshold value is 5. |
Conclusion
If poison messages stay on top of queue, other messages will never get a chance
to be de-queued by listener programs. As a matter of practice, if message
processing fails, it's always a good idea to retry, but not indefinitely. If
messages still fail, messages should be moved out to another queue to be
debugged later by an admin. A backout queue offers an excellent buffer for
storing such poison messages to let the application run at a normal pace.
WebSphere MQ keeps track of number of times a message has been backed out. Once
this configurable threshold value is reached, they can be moved to a backout
queue. Note that MQ will not automatically move poison messages; it's the
responsibility of the application program to move them to a backout queue.
The Eclipse view of the output of sample app. The program gets the first message on the queue and then backs it out until the backout threshold is reached. |