[rabbitmq-discuss] Channel thread safety in Java client

Jiri Krutil jiri at krutil.com
Thu Jul 7 17:16:06 BST 2011


Steve,

Can you please clarify your post a bit for me:

You say that a client application may continue to use a Channel from  
its main thread even if the RabbitMQ client library uses the same  
Channel for async receiving.

How is the use of a Channel from the RabbitMQ client library  
connection thread sychronized with the use of the same Channel from  
the client application thread?

Is such concurrent Channel access different from a situation when two  
client application threads access the same Channel concurrently?

Cheers
Jiri


> Jiri,
> The current implementation of the Java Client calls the Consumer  
> interface on the same thread that the Channel work is done on.  This  
> means that anything done in the Consumer callbacks is synchronised  
> with all the other channel stuff going on, and could potentially  
> block it.  There are notes on the api-guide pages to warn you about  
> this.
>
> The QueueingConsumer class basically makes sure that the Consumer  
> callbacks do not cause any problems, putting the messages on the  
> (dedicated) queue for any (usually the main) thread to access them.
>
> This means that, even though there may be many consumers defined for  
> a Channel, ownership of the Channel is not passed to the 'lib's  
> connection thread', and you can continue to use the Channel from the  
> main thread, or whatever thread you have allocated to run it from.   
> You can ack messages, and anything else you want, too.
>
> The thing you shouldn't do is to call Channel methods (for the same  
> channel) from more than one thread at a time.  This is because the  
> threading model in the channel is 'challenged'.
>
> We are currently working on the Consumer and Channel threading  
> restrictions -- we want to run all the Consumer callbacks on a  
> thread which is distinct from the Connection thread; and allow  
> channels to be driven from multiple threads.  This would mean it is  
> feasible to do most Channel operations from the Consumer callback  
> itself, and from any other thread.
>
> Incidentally, the way our changes are going at the moment, we will  
> expose the execution thread pool for Consumer callbacks; and allow  
> the user to have control over how many threads are allocated.  For  
> example, it might be thought sensible to have a single thread per  
> channel allocated for Consumer callbacks; but this could mean a  
> large penalty for a large number of channels that may be doing very  
> little work.  Instead we pass work to an Executor (managed so that  
> all the work required by a single channel is serialised) which runs  
> it on a thread from a pool.  The default Executor will use a (fixed)  
> pool of 16 threads, but the interface will allow passing in any  
> Executor implementation for the Connection.
>
> I hope this helps.  Feedback is welcome.
> Steve Powell  (a happy bunny)
> ----------some definitions from the SPD----------
> Rigatoni n. A prime-ministerial grin.
> Nigella n. The next bottle-size up from a Nebuchadnezzar.
> Homily adv. Rather like a frenchman.
>
> On 5 Jul 2011, at 09:42, Jiri Krutil wrote:
>
>> Hi
>>
>> I'm trying to understand the limitations of using a Channel in a
>> multi-threaded application using the Java client. Sorry for this longish
>> post...
>>
>> I have read http://www.rabbitmq.com/api-guide.html#channel-threads but
>> did not find any other, more detailed info.
>>
>> I want to receive messages by subscription. I create a Channel and
>> invoke basicConsume() on it, passing a QueueingConsumer.
>>
>> The moment I call basicConsume(), I would imagine the Channel becomes
>> "owned" by the client lib's connection thread, which feeds messages to
>> QueueingConsumer.
>>
>> My app is retrieving those messages from the QueueingConsumer in the
>> main thread. I would like to know to which extent can I keep using the
>> Channel passed to basicConsume() from the main thread.
>>
>> I guess I can use it to ack messages, because ack would not work on
>> another channel, correct? Can I also use the channel for other things,
>> such as sending messages, using transactions, or starting another
>> subscription?
>>
>> JMS specs seem to be quite explicit on this. It says a session with an
>> active subscription is owned by the connection thread and client app
>> threads cannot use the session; they can only shut it down. That's why
>> if I want multiple subscriptiopns on one session, I must set them all up
>> before I call Connection.start(), which passes the session ownership to
>> the client library. Afterwards I can no longer use the session from my
>> threads except closing it.
>>
>> Could you please elaborate on how exactly this works in the rabbit Java
>> client?
>>
>> Cheers
>> Jiri
>>
>> _______________________________________________
>> rabbitmq-discuss mailing list
>> rabbitmq-discuss at lists.rabbitmq.com
>> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
>
>





More information about the rabbitmq-discuss mailing list