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

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


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/4b90638f/attachment.html>


More information about the rabbitmq-discuss mailing list