quanticle
quanticle

Reputation: 5020

Why do my RabbitMQ channels keep closing?

I'm debugging some Java code that uses Apache POI to pull data out of Microsoft Office documents. Occasionally, it encounter a large document and POI crashes when it runs out of memory. At that point, it tries to publish the error to RabbitMQ, so that other components can know that this step failed and take the appropriate actions. However, when it tries to publish to the queue, it gets a com.rabbitmq.client.AlreadyClosedException (clean connection shutdown; reason: Attempt to use closed channel).

Here's the error handler code:

try {
    //Extraction and indexing code
}
catch(Throwable t) {
    // Something went wrong! We'll publish the error and then move on with
    // our lives
    System.out.println("Error received when indexing message: ");
    t.printStackTrace();
    System.out.println();
    String error = PrintExc.format(t);
    message.put("error", error);

    if(mime == null) {
        mime = "application/vnd.unknown";
    }

    message.put("mime", mime);
    publish("IndexFailure", "", MessageProperties.PERSISTENT_BASIC, message);
}

For completeness, here's the publish method:

private void publish(String exch, String route, 
    AMQP.BasicProperties props, Map<String, Object> message) throws Exception{
    chan.basicPublish(exch, route, props, 
        JSONValue.toJSONString(message).getBytes());  
}

I can't find any code within the try block that appears to close the RabbitMQ channel. Are there any circumstances in which the channel could be closed implicitly?

EDIT: I should note that the AlreadyClosedException is thrown by the basicPublish call inside publish.

Upvotes: 47

Views: 150522

Answers (6)

Ahmad Abdelghany
Ahmad Abdelghany

Reputation: 13248

Apparently, there are many reasons for the AMQP connection and/or channels to close abruptly. In my case, there was too many unacknowledged messages on the queue because the consumer didn't specify the prefetch_count so the connection was getting terminated every ~1min. Limiting the number of unacknowledged messages by setting the consumer's prefetch count to a non-zero value fixed the problem.

channel.basicQos(100); 

Upvotes: 7

la0rg
la0rg

Reputation: 51

For those who wonder why their consuming channels are closing, check if you try to Ack or Nack a delivery more than once.

In the rabbitmq log you would see messages like:

operation basic.ack caused a channel exception precondition_failed: unknown delivery tag ...

Upvotes: 2

denil
denil

Reputation: 690

I'd like to add this information for other users who will be searching for this topic

Another possible reason for Receiving a Channel Closed Exception is when Publishers and Consumers are accessing Channel/Queue with different queue declaration/settings

Publisher

channel.queueDeclare("task_queue", durable, false, false, null);

Worker

channel.queueDeclare("task_queue", false, false, false, null);

From RabbitMQ Site

RabbitMQ doesn't allow you to redefine an existing queue with different parameters and will return an error to any program that tries to do that

Upvotes: 9

Morteza Mashayekhi
Morteza Mashayekhi

Reputation: 934

I also had this problem. The reason for my case was that, first I built the queue with durable = false and in the log file I had this error message when I switched durable to true:

"inequivalent arg 'durable' for queue 'logsQueue' in vhost '/': received 'true' but current is 'false'"

Then, I changed the name of the queue and it worked for me. I assumed that the RabbitMQ server keeps the record of the built queues somewhere and it cannot change the status from durable to non-durable and vice versa.

Again I made durable=false for the new queue and this time I got this error

"inequivalent arg 'durable' for queue 'logsQueue1' in vhost '/': received 'false' but current is 'true'"

My assumption was true. When I listed the queues in rabbitMQ server by:

rabbitmqctl list_queues 

I saw both queues in the server.

To summarize, 2 solutions are: 1. renaming the name of the queue which is not a good solution 2. resetting rabbitMQ by:

rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app

Upvotes: 1

Christoph
Christoph

Reputation: 4000

Another reason in my case was that by mistake I acknowledged a message twice. This lead to RabbitMQ errors in the log like this after the second acknowledgment.

=ERROR REPORT==== 11-Dec-2012::09:48:29 ===
connection <0.6792.0>, channel 1 - error:
{amqp_error,precondition_failed,"unknown delivery tag 1",'basic.ack'}

After I removed the duplicate acknowledgement then the errors went away and the channel did not close anymore and also the AlreadyClosedException were gone.

Upvotes: 23

alanxz
alanxz

Reputation: 2026

An AMQP channel is closed on a channel error. Two common things that can cause a channel error:

  • Trying to publish a message to an exchange that doesn't exist
  • Trying to publish a message with the immediate flag set that doesn't have a queue with an active consumer set

I would look into setting up a ShutdownListener on the channel you're trying to use to publish a message using the addShutdownListener() to catch the shutdown event and look at what caused it.

Upvotes: 61

Related Questions