5

We are using the .NET API to IBM's WebSphere MQ.

Creating the MQQueueManager object is clearly an expensive operation, and so we cache and reuse a pool of these objects.

Currently, for each request, we access the required queues:

//obtain queueManager from pool
IBM.WMQ.MQQueue requestQ= queueManager.AccessQueue(requestQName, mqOptions);
IBM.WMQ.MQQueue responseQ= queueManager.AccessQueue(responseQName, mqOptions);

and close them once done:

requestQ.Close();
responseQ.Close();

Is this best practice, or should we be also pooling and reusing the MQQueue objects (in addition to the queue manager)? AccessQueue() appears to be a cheap operation on the client.

T.Rob
  • 31,522
  • 9
  • 59
  • 103
MJ Richardson
  • 1,441
  • 12
  • 30

1 Answers1

0

The answer depends on your threading model and transactionality. In general, messaging clients should always use transactionality, even if that is only single-phase commit. The reason is that there are ambiguities of outcomes that can cause duplicate or lost messages otherwise. I've provided a much more detailed explanation of this in another answer.

The issue is that transactions are connection-scoped. When you COMMIT you do so for the entire connection. Using the same connection across several threads safely would preclude the use of transactions and thus expose the app to lost or duplicate messages. Since queue handles are only valid in the context of a particular connection, they inherit from your threading model and connection pool.

The most common model for a service provider application is to maintain a connection per-thread on the input queue and dynamically open/put/close the output queue. For example, in a single unit of work...

  1. Read the next request message
  2. Use the reply-to information to obtain the destination
  3. Open the reply-to queue
  4. Put the response
  5. Commit
  6. Destroy the reply-to destination object and thus close the reply-to queue

In this case the connections are not constantly rebuilt, nor is the input queue ever closed. However, it does require each thread to maintain a dedicated connection.

Community
  • 1
  • 1
T.Rob
  • 31,522
  • 9
  • 59
  • 103
  • Well you say "connection", what do you mean? I see that IBM docs also refer to it, but since I think I'm *connected* to a QueueManager, I don't really understand whether I need to create a new QM for each thread (caching it) or not. – Bruno Brant Oct 28 '16 at 16:15
  • This answer does not deal with IBMs MQ implementation at all - as long as you do (at least) not mention that i vote it down. – Florian Neumann Apr 12 '18 at 16:16
  • Thanks for the explanation of the downvote. If the answer relied on MQ-specific behavior I would happily update to point that out. However the question and the answer both rely on behavior that in IBM's implementation conforms to the JMS spec and can be described effectively in that context. You are of course free to take exception to that approach and I appreciate the explanation, but I'm comfortable with the response as written. – T.Rob Apr 14 '18 at 03:32