Low Orbit Flux Logo 2 F

RabbitMQ How to Remove Unacked Message

When using RabbitMQ there are situations where you might want to remove unacked messages. You could end up with a polluted environment if you don’t get things cleaned up. It can also be an indicator of something that is broken such as a stuck consumer.

To remove unacked messages in RabbitMQ:

We’re going to show you how to do this from the command line and from the management GUI.

Show queues with unacked connections like this.

rabbitmqctl list_queues name messages messages_unacknowledged

To find the channel with unacked messages you can use the following command. It will also show the connection that is associated with the channel.

rabbitmqctl list_channels connection messages_unacknowledged

You can close the channel like this. Specify the connection that was associated with the channel found above. The last parameter is a message that will be sent to the consumer and will appear in the consumer’s error message.

rabbitmqctl close_connection "<rabbit@zippy-zap.1608598465.5412.0
>" "go away"

As an alternative to the step above you could just manually kill the process for the consumer that is associated with the channel.

You can use the following command to verify that you no longer have any unacked messages but these same messages should be in the “Ready” state.

rabbitmqctl list_queues name messages messages_unacknowledged

If you want the messages to be removed from the queue this can be done by purging them with either of the following commands.

rabbitmqctl purge_queue hello
rabbitmqadmin purge queue name=hello

You can complete these same steps using the management GUI.

You can view channels and unacked messages here on the “Channels” tab but you will want to go to the “Connections” tab to actually close them.

RabbitMQ channel with unacked messages

To start off you can see all of your connections on the “Connections” tab like this. Just click on one of them to view it.

Remove unacked message - RabbitMQ connection1

When you view a specific connection you can see the number of unacked messages on each of its channels. Just click the “Force Close” button to close the connection.

Remove unacked message - RabbitMQ connection2

Next you can go to the “Queues” tab. Here you should be able to see that there are no unacked messages. The messages that were previously in an unacked state should now be in a “Ready” state. Select a queue to purge.

Remove unacked message - RabbitMQ queue

Click on the “Purge Messages” button to clear all messages from the queue.

Remove unacked message - RabbitMQ queue purge

RabbitMQ Unacked Message Cause

One thing that can cause unacked messages to build up for a consumer is forgetting to ack messages. If auto_ack is not turned on then an ack needs to be sent manually. If this is forgotten or just not done it will cause unacked messages to build up. Here is an example of broken consumer code that omits the ack line from the call back function.

import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)

channel.basic_consume(queue='hello', on_message_callback=callback)
channel.start_consuming()
connection.close()

You can fix this by placing a call to “basic_ack” at the end of the callback function like this:

def callback(ch, method, properties, body):
    print(" [x] Received %r" % body.decode())
    time.sleep(2)
    print(" [x] Done")
    ch.basic_ack(delivery_tag = method.delivery_tag)

You can also fix this by enabling “auto_ack” which may or may not be the right thing to do depending on the situation:

channel.basic_consume(queue='hello',
                      auto_ack=True,
                      on_message_callback=callback)

Extra Info

You can close a channel programmatically like this:

channel.close()

When you close a connection all channels on that connection will also be closed. You can close a connection programmatically like this:

connection.close()