MQ

IBM MQ Little Gem #50: Bind Not Fixed

By Morag Hughson posted Wed January 27, 2021 12:26 AM

  
This is part of a series of small blog posts which will cover some of the smaller, perhaps less likely to be noticed, features of IBM MQ. Read other posts in this series.

I asked the team during the recent "IBM MQ: Ask Us Anything" event, what their favourite little feature of IBM MQ was. You can watch the full replay of that webinar here. David Ware's answer was about Bind Not Fixed in MQ Clustering. So let's learn a little about that little gem of a feature today.

One of the great benefits of IBM MQ Clustering is the idea of workload balancing. Imagine that you have a number of queue managers, three in our diagram, hosting a queue that fronts a service driven by messages. IBM MQ Clustering will choose a queue manager to send a message to when an application puts a message to that queue name, Q1 in our diagram. This "choosing" process has two main modes, Bind on Open and Bind not Fixed.

Simple MQ Cluster

Bind on Open

In this mode, the choosing process happens when the application opens the queue, Q1. The implication of this is that no further choosing happens when each message is put, meaning that all the messages go to the same instance of the queue, i.e. to the same queue manager. To re-drive the choosing process, the application must close and re-open the queue. This usually means that the application only sees a different choice when it is restarted as many applications only open the queue at the start of the application.

This may sound like you have turned off workload balancing completely, but there is still some balancing going on. At the time the application opens the queue, the choice is made, so if one queue manager is offline at that time, or the network to it is problematic and the channel is retrying, a different queue manager will be chosen.

This option is the default setting for one and only one reason. It was considered, when IBM MQ Clustering was created, that the default settings must be "safe" for applications that have conversational style messaging, or that send a number of messages that must all go to the same location. Applications that had these requirements were said to have an affinity to - that is the need to continue using - the same instance of the service.

If your application doesn't have such affinities, you can explicitly use, or change the default to use the "Bind not Fixed" mode.

From David's answer (which you can watch below) it seems that many users of IBM MQ Clustering are not aware that they can have a different behaviour to this default way of doing things.

Bind not Fixed

In this mode, the choosing process happens at each put of a message, and additionally at some other very helpful times which we will discuss in a moment.

By making a different choice on each put of a message, this can break a conversational application. If message 1 goes to queue manager 1, and then message 2 goes to queue manager 2; if queue manager 2 needs to see message 1 in order to make sense of message 2, this won't work for your application. This is why the "Bind on Open" mode is the default.

However, many/most applications do not have this affinity, and a work request is encapsulated in a single message. This means that workload balancing each individual message is appropriate and useful. The workload from one, and from many, applications can be spread across all the queue managers that are available to process them.

In addition to choosing an available queue manager with running channels to send your message to, this mode has an additional helpful action. If messages that were put using "Bind not Fixed" later get stuck because the channel that was to move them has a failure, goes into retry and isn't able to connect right now, there is help at hand! These messages, currently sitting on a cluster transmission queue, are automatically sent through the choosing process again to find a better, more available queue manager to send them to. This is very helpful because now you know that if you using this mode, MQ will find a way to get your messages to an available queue hosted by an available queue manager if there is at least one to go to. You don't have to manage this yourself, the clustering feature of IBM MQ will take care of it all for you.

Choosing one mode or the other

There are two ways to change the default. There is a queue attribute and there is a programmatic option.

Programmatic option

In an application, when you MQOPEN a queue, there are various options you can set, e.g. MQOO_OUTPUT to say that you want to put messages to this queue. One of the following options can be used to choose the mode you want:-

  • MQOO_BIND_ON_OPEN
  • MQOO_BIND_NOT_FIXED
  • MQOO_BIND_ON_GROUP (specifically for grouped messages, not discussed today)

Here's some sample code using MQOO_BIND_NOT_FIXED.

MQOD   od = {MQOD_DEFAULT};
MQLONG OpenOptions;

strncpy(od.ObjectName, inputQueueName, MQ_Q_NAME_LENGTH);
OpenOptions = MQOO_OUTPUT
            | MQOO_BIND_NOT_FIXED
| MQOO_FAIL_IF_QUIESCING; MQOPEN(hConn, &od, OpenOptions, &hObj, &CompCode, &Reason);

If your code does not use any of the above options, then you automatically pick up the behaviour of the zero-value MQOO_BIND_AS_Q_DEF option. This means that you make use of the queue attribute which we will look at next.

In case it is not obvious, the queue attribute is only used if the application does not use any of the above options, so the application has full control of the behaviour here and can over-ride the queue attribute quite easily.

Queue Attribute

If the application has not made use of any of the programmatic options, then the queue attribute comes into play. This attribute is called "Default Bind Option" or DEFBIND in MQSC. That is, it is the option to be used if the application left the value as the default.

Similar to the programmatic options, here are the administration queue attribute values:-

  • DEFBIND(OPEN)
  • DEFBIND(NOTFIXED)
  • DEFBIND(GROUP)

If you are creating a new cluster queue, you can make sure it is using the "Bind not Fixed" mode immediately, by defining it like this:-

DEFINE QLOCAL(Q1) CLUSTER(MQGEM) DEFBIND(NOTFIXED)

Or, if you want to change an existing cluster queue because you know your application has no affinities, you can change the queue like this:-

ALTER QLOCAL(Q1) DEFBIND(NOTFIXED)

To finish, let's listen to a snippet of the Ask Us Anything webinar, where David Ware describes this feature in his own words.

You can watch the full replay of that webinar here.

Also, there's a new Hursley webinar about IBM MQ in the calendar for March. You can register here.


Morag Hughson is an MQ expert. She spent 18 years in the MQ Devt organisation before taking on her current job writing MQ Technical education courses with MQGem. She also blogs for MQGem. You can connect with her here on IMWUC or on Twitter and LinkedIn.

#Little-Gem
#IBMMQ
#ChampionsCorner
#Featured-area-1
#Featured-area-1-home
1 comment
270 views

Permalink

Comments

Fri January 29, 2021 12:30 PM

Thanks Morag, great explanation.

The extra thing about this that is particularly well hidden is that the bind behaviour is not only binding those messages to a specific queue manager when you initially open the queue or put the message, you’re also determining whether MQ can change its mind in the future.

So why would we want to do that? The scenario is that at the time the queue is opened or the message put, the chosen queue manager is available (based on the channel state), but maybe there’s a backlog on the transmission queue and by the time the message can be transmitted that queue manager in no longer there. This could be thousands of messages waiting or just a single unfortunate one.

If the application used bind not fixed, MQ will automatically say “I can’t get these messages to QMGR1, I’ll go round the loop again and find a better target, let’s try QMGR2…”. However, if they’ve used bind on open, MQ has to err on the side of caution, assuming that the sender really wants to get these messages to the original queue manager even though it’s not currently available (which is fair, as you might be half way through a set of related messages). So those messages will have to wait for QMGR1 to come back up, however long that takes.

So you can see that bind not fixed can really help with routing messages around failures quickly, whereas bind on open can easily get in the way, even if you're just sending one message per open. So if you have no need for bind on open, I suggest you don’t use it!

(For anyone interested, this is a useful delve into the details)