[rabbitmq-discuss] How to shutdown cleanly a Java application using Consumers?

Gary Russell grussell at gopivotal.com
Wed Apr 2 23:34:42 BST 2014


I just took another look at the client - with the default (internal
private) ExecutorService, it does an orderly shutdown() which won't
interrupt the threads.

If you pass in your own ExecutorService to newConnection() you can call
shutDownNow() which *will* interrupt the dispatcher threads (if they are
doing something that's interruptible).

See ExecutorService.shutDownNow() for more information.

Gary


On Wed, Apr 2, 2014 at 6:23 PM, Gary Russell <grussell at gopivotal.com> wrote:

> In Spring-AMQP, we don't asynchronously cancel the consumer, we tell the
> consumer it needs to cancel itself when it's finished its current work.
> IIRC, if the consumer is running when you cancel it, its basicAck will fail
> because you've already cancelled it and the broker has re-queued that
> message. Effectively we tell the consumer to emit the cancel immediately
> after the ack.
>
> >stop a badly behaving Consumer
>
> It depends on how badly behaved it is; if it never executes any
> interruptible code (say it's stuck in a while() loop), you are out of luck.
> If it does stuff that's interruptible (acquire locks, etc, etc) then you
> can interrupt it.
>
> I don't know enough about the rabbit client internals as to whether there
> is a mechanism to force it to interrupt the dispatcher thread (I didn't see
> anything after a quick look) so you might have to roll your own (capture a
> reference to the thread in handleDelivery and interrupt it after your
> timeout).
>
> When all else fails, System.exit() is your friend.
>
> Gary
>
>
>
> On Wed, Apr 2, 2014 at 5:52 PM, Bertrand Guay-Paquet <
> bernie at step.polymtl.ca> wrote:
>
>> Thanks Jason and Gary,
>>
>> Your replies really helped and I almost got it now. At first, I didn't
>> know that handleCancelOk only runs when a consumer is not handling anything
>> else. That is, only a single handle*() method can run at the same time on
>> any given consumer instance. Thinking about it now, I realize this was
>> explained in the doc with the phrase "Each Channel has its own dispatch
>> thread."
>>
>> So I created my subclass of DefaultConsumer (BasicConsumer) which
>> implements isCancelled() and handleCancelOk() which sets a "cancelled flag"
>> to true. Is there already a built-in way to know if a consumer was
>> cancelled? I couldn't find it myself...
>>
>> Here are my start and stop sequences which almost completely work. I
>> haven't found how to forcefully stop a badly behaving Consumer after a
>> given timeout at the end of the stop sequence. How can this be achieved?
>>
>> Start sequence:
>> consumers = new ArrayList<BasicConsumer>();
>> consumers.add(...)
>>
>> Stop sequence:
>> // Cancel all consumers
>> for (BasicConsumer consumer : consumers) {
>>   try {
>>     consumer.getChannel().basicCancel(consumer.getConsumerTag());
>>   } catch (Exception e) {
>>     // report
>>   }
>> }
>>
>> // Wait for all consumers to be cancelled
>> Timeout timeout = ...;
>> while (!consumers.isEmpty() && !timeout.isElapsed()) {
>>   // Remove cancelled consumers
>>   for (Iterator<BasicConsumer> iterator = consumers.iterator();
>> iterator.hasNext();) {
>>     if (iterator.next().isCancelled())
>>       iterator.remove();
>>   }
>> }
>>
>> // Force close remaining (timed-out) consumers
>> for (BasicConsumer consumer : consumers) {
>>   consumer.getChannel().abort(); // <---- doesn'k kill the consumer
>>   // <---------------- How do I kill a timed-out consumer?
>> }
>> connection.close();
>>
>> Regards,
>> Bertrand
>> _______________________________________________
>> rabbitmq-discuss mailing list
>> rabbitmq-discuss at lists.rabbitmq.com
>> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/attachments/20140402/86bc7586/attachment.html>


More information about the rabbitmq-discuss mailing list