|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
MQCB and MQCTL multi-thread issue |
« View previous topic :: View next topic » |
Author |
Message
|
RogerLacroix |
Posted: Sun Nov 10, 2013 8:53 pm Post subject: MQCB and MQCTL multi-thread issue |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
All,
I'm stuck. Help.
I am trying out the MQCB and MQCTL API calls (using WMQ v7.5) to have messages pushed to an async message consumer.
My code dumps out the PID (Process Id) and TID (Thread Id) of the main process and in the async message consumers. I can see that all have the same PID, which is expected and they have different TIDs. The issue I am having is that all message consumers are running under the same TID. i.e. one TID for the main process and one TID for all message consumer.
I have done testing where the MQOPEN, MQCB & MQCTL are against 3 different queues and testing where they are against the same queue. I tried using MQCTLO_THREAD_AFFINITY and without but it made no difference. No matter what I do, I cannot get the message consumers under different TIDs (different from each other).
It is hard to say that the message consumers are running aync when they all use the same TID. I even tried out the MQ sample code called: amqscbf0.c and got the same result. Because all message consumers are using the same TID, the log shows that basically messages are being consumed (from the 3 queues) in a round-robin fashion. But what I want is the 3 message consumers to run in parallel (which can only be done using different TIDs).
I have read and reread the MQ InfoCenter but I cannot figure it out.
What option/parameter do I use to get the combination MQOPEN, MQCB & MQCTL API calls to force the message consumers to be on different TIDs (from each other)?
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
fjb_saper |
Posted: Sun Nov 10, 2013 10:40 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
Open a different connection for each async consumer. I believe that your problem is that the messages are synchronized through the connection, hence the round robing... Try opening a different connection for each async consumer and let us know how you fare... AFAIK that's how it's being handled in JMS/XMS  _________________ MQ & Broker admin |
|
Back to top |
|
 |
PaulClarke |
Posted: Sun Nov 10, 2013 11:45 pm Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
Hi Roger,
I’m not quite sure I understand your question. The main question, I guess, is how many connections do you have ? If you only have one connection then I am surprised that you would expect MQ to call 3 different consumers on 3 different threads at the same time. It would be much more inefficient to keep bouncing between threads. Bear in mind that if you only have one connection then MQ can only deliver one message to one consumer at once. This is obvious if you think what that consumer might do. For example, if you issued MQCMIT() in the consumer you clearly can not risk committing messages in other consumers. So, MQ will ensure that you only have one thing going on at once. Async. consume has many advantages over a traditional MQGET but allowing multiple parallel connections on one HCONN is not one of them
Cheers,
P. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
RogerLacroix |
Posted: Mon Nov 11, 2013 9:48 am Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
fjb_saper wrote: |
Open a different connection for each async consumer. I believe that your problem is that the messages are synchronized through the connection, hence the round robing... Try opening a different connection for each async consumer and let us know how you fare... AFAIK that's how it's being handled in JMS/XMS  |
Yes, I know all of that (me thinks you forget who you are talking to).
Ok. Maybe I should have included the following: 5% (or less) of the work performed by the TID will be related to MQ. Hence, 95% will be backend non-MQ work.
PaulClarke wrote: |
I guess, is how many connections do you have ? If you only have one connection then I am surprised that you would expect MQ to call 3 different consumers on 3 different threads at the same time. |
One. I never said I wanted 3 MQ API to be performed at the same time, what I said was I wanted each message consumer to be running in its own thread.
PaulClarke wrote: |
For example, if you issued MQCMIT() in the consumer you clearly can not risk committing messages in other consumers. So, MQ will ensure that you only have one thing going on at once. |
True. And that is why I explicitly set the GMO option to MQGMO_NO_SYNCPOINT which is used on the MQCB call. I am trying to figure how to tell MQ library that I am ok with round-robin at the connection level but I want each message consumer to be started in a separate thread.
PaulClarke wrote: |
Async. consume has many advantages over a traditional MQGET but allowing multiple parallel connections on one HCONN is not one of them |
That's not what I want. I want each message consumer to be started in a separate thread.
Each message will be less than 1KB that the message consumer will receive. As mentioned, 5% (or less) of the work performed by the thread will be related to MQ and 95% will be backend non-MQ work.
In this case, the bottleneck is not MQ but all of the backend work that the message consumer needs to do. Hence, if each message consumer is started in its own thread, then the application can do more non-MQ work (parallel processing for the backend work).
Does that make more sense?
So, does anyone know of a flag, parameter or environment variable to tell the MQ library to start each message consumer in its own thread?
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
PaulClarke |
Posted: Mon Nov 11, 2013 10:08 am Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
It does make more sense but I'm not sure you are trying to use MQ incorrectly. Async. consumer is not a scheduler, MQ is not donating threads to the application. The thread is MQ's and should be used for messaging. As it says in the manual....
Quote: |
Be aware that if your callback routines use services that could delay or block the thread, for example, MQGET with wait, this could delay the dispatch of other callbacks. |
The 'problem' from MQs point of view is that whenever you are in a consumer function you are entitled to issue an MQI call using the given HCONN. Now, in your case you might be sure that your application isn't going to do it but MQ doesn't know this. If in your consumer you did decide to issue MQCMIT() or MQPUT() or any other verb you would expect it to work. You wouldn't expect to be told 'connection busy' because some other consumer is doing something.
I think your two choices are really:
1/ Create a separate connection for each consumer.
Note that in a client you probably have to also say MQCTLO_THREAD_AFFINITY in order to get a thread dedicated to a single connection since the client won't do that by default.
2/ Create a work thread yourself and dispatch the message to it when you get it
Cheers,
Paul. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
RogerLacroix |
Posted: Mon Nov 11, 2013 1:53 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
PaulClarke wrote: |
It does make more sense but I'm not sure you are trying to use MQ incorrectly. Async. consumer is not a scheduler, MQ is not donating threads to the application. The thread is MQ's and should be used for messaging. As it says in the manual....
Quote: |
Be aware that if your callback routines use services that could delay or block the thread, for example, MQGET with wait, this could delay the dispatch of other callbacks. |
|
True. I was treating it as MQ created a thread for the application to process that particular message.
Usage Note # 5 is what put me on this path thinking that there would be more than 1 thread created:
Quote: |
A callback routine should not, in general, rely on being invoked from the same thread each time. If this is required, use the MQCTLO_THREAD_AFFINITY when the connection is started. |
So, the MQ library can and/or may create different threads when starting a message consumer. I don't care about connection/message affinity. If every start of a message consumer was in a new (unique) thread that would be fine with me (actually preferred!!!).
PaulClarke wrote: |
I think your two choices are really:
1/ Create a separate connection for each consumer.
Note that in a client you probably have to also say MQCTLO_THREAD_AFFINITY in order to get a thread dedicated to a single connection since the client won't do that by default.
2/ Create a work thread yourself and dispatch the message to it when you get it |
How exactly would you do number 1 if you did not first create a work thread?
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
PaulClarke |
Posted: Mon Nov 11, 2013 2:06 pm Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
I'm not sure I understand your question. Just issue as many MQCONNs as you need in the same thread, one after the other. You will, of course, need to make them shared handles....ie. something like MQCNO_HANDLE_SHARE_BLOCK
Cheers,
Paul. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
RogerLacroix |
Posted: Mon Nov 11, 2013 4:30 pm Post subject: |
|
|
 Jedi Knight
Joined: 15 May 2001 Posts: 3264 Location: London, ON Canada
|
PaulClarke wrote: |
Just issue as many MQCONNs as you need in the same thread, one after the other. You will, of course, need to make them shared handles....ie. something like MQCNO_HANDLE_SHARE_BLOCK |
How in the world did you get that from the manual?
For MQCNO_HANDLE_SHARE_BLOCK, the manual says
Quote: |
Creates a shared connection. On a MQCNO_HANDLE_SHARE_BLOCK connection, if the connection is currently in use by an MQI call on another thread, the MQI call waits until the current MQI call has completed. |
Where does it say that option allows you to create multiple connections per thread?
Don't get me wrong - this IS what I was looking for. I added the option and put MQCONNX, MQOPEN, MQCB and MQCTL in a loop and viola, I get the number of threads for the message consumer as the loop counter is set for. Bingo.
Should I be using MQCTLO_THREAD_AFFINITY option with MQCTL? I tried it with and without but it did not seem to make any difference.
Regards,
Roger Lacroix
Capitalware Inc. _________________ Capitalware: Transforming tomorrow into today.
Connected to MQ!
Twitter |
|
Back to top |
|
 |
PaulClarke |
Posted: Mon Nov 11, 2013 10:51 pm Post subject: |
|
|
 Grand Master
Joined: 17 Nov 2005 Posts: 1002 Location: New Zealand
|
I agree that the manual could be a lot clearer and perhaps this is worthy of a manual update. Shared Handles have been around for many releases, nothing to do with async consume, it would be a shame if most people don't know about them.
As far as using MQCTLO_THREAD_AFFINITY is concerned I think you probably should use it. It's not really what the option is for but if I recall it will have the right affect as a side effect on a client. Be aware that the threading on the server and client is a little different and, of course, may change in the future. However, from what I remember the situation is this:
a) on the server
A thread dedicated to the connection is created as soon as MQCTL is issued and the thread will run for the life of async consume. So, MQCTLO_THREAD_AFFINITY will have no effect since it is doing it anyway.
b) on the client
By default the connection is only associated with a thread when there are messages to be delivered and more than one connection can be associated with the same thread at any one time. This reduces the thread usage. For example it is possible to have 100 connections to the queue manager all with started consumers and yet there be 0 threads in the background to deliver the messages. However, if I recall correctly then specifying MQCTLO_THREAD_AFFINITY will cause the client to dedicate a thread to the connection just like the server. So, in the case of the client I think you should indeed use MQCTLO_THREAD_AFFINITY.
Of course the bottom line is to try it and see what effect you see. If you do find it works then I think it might also be worth getting a manual update no this behaviour since if you are relying on it you don't want MQ to change the dispatching model underneath you. This isn't really what MQCTLO_THREAD_AFFINITY was about after all but it is an understandable by-product.
Cheers,
Paul. _________________ Paul Clarke
MQGem Software
www.mqgem.com |
|
Back to top |
|
 |
mvic |
Posted: Wed Nov 13, 2013 5:29 pm Post subject: |
|
|
 Jedi
Joined: 09 Mar 2004 Posts: 2080
|
RogerLacroix wrote: |
PaulClarke wrote: |
Just issue as many MQCONNs as you need in the same thread, one after the other. You will, of course, need to make them shared handles....ie. something like MQCNO_HANDLE_SHARE_BLOCK |
How in the world did you get that from the manual? |
Search the mq info center for the words
I am sure the IBM feedback link can be used to tell them how to make this information more accessible or more obvious. |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|