Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do my RabbitMQ channels keep closing?

Tags:

java

rabbitmq

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.

like image 360
quanticle Avatar asked Jan 12 '12 17:01

quanticle


People also ask

How many channels can RabbitMQ handle?

You can use one Channel for everything. However, if you have multiple threads, it's suggested to use a different Channel for each thread. Channel instances are safe for use by multiple threads. Requests into a Channel are serialized, with only one thread being able to run a command on the Channel at a time.

Should I reuse RabbitMQ channel?

Don't open and close connections or channels repeatedly. Even channels should be long-lived if possible, e.g., reuse the same channel per thread for publishing. Don't open a channel each time you are publishing.

How many messages can a RabbitMQ queue hold?

Queues are single-threaded in RabbitMQ, and one queue can handle up to about 50 thousand messages.

What is the difference between channel and queue in RabbitMQ?

Queue: Buffer that stores messages. Message: Information that is sent from the producer to a consumer through RabbitMQ. Connection: A TCP connection between your application and the RabbitMQ broker. Channel: A virtual connection inside a connection.


6 Answers

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.

like image 156
alanxz Avatar answered Sep 23 '22 03:09

alanxz


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.

like image 28
Christoph Avatar answered Sep 22 '22 03:09

Christoph


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
like image 41
denil Avatar answered Sep 24 '22 03:09

denil


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); 
like image 39
Ahmad Abdelghany Avatar answered Sep 24 '22 03:09

Ahmad Abdelghany


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
like image 22
Morteza Mashayekhi Avatar answered Sep 26 '22 03:09

Morteza Mashayekhi


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 ...

like image 39
la0rg Avatar answered Sep 26 '22 03:09

la0rg