RabbitMQ-message confirmation

Posted May 27, 20204 min read

RabbitMQ-Queue mentioned that when receiving a message, there are two ways, one is consume and the other is get. Both methods have an autoAck parameter . When we set it to true, it means that the consumer will send an acknowledgment to rabbitmq through AMQP, rabbitmq will automatically confirm the message and delete the message from the queue. The following uses the consume method to do some examples to understand the parameter setting of autoAck.

String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

GetResponse basicGet(String queue, boolean autoAck) throws IOException;

not sure

First send 5 data to the ack queue, you can see that ready is 5, and total is 5.
image.png
Run the following code, autoAck is set to false, and the message is not confirmed.

public static void main(String []args) throws IOException, TimeoutException {
    //Declare a connection factory
    ConnectionFactory factory = new ConnectionFactory();
    //Create a connection to the rabbitmq server
    Connection connection = factory.newConnection();
    //Create a Channel
    Channel channel = connection.createChannel();
    //Define the queue through Channel
    channel.queueDeclare("ack", false, false, false, null);
    //Asynchronous callback processing
    DeliverCallback deliverCallback =(consumerTag, delivery)-> {
        String message = new String(delivery.getBody(), "UTF-8");
        System.out.println("ack Received '" + message + "'" + delivery.getEnvelope(). GetDeliveryTag());
        //channel.basicAck(delivery.getEnvelope(). getDeliveryTag(), false);
    };
    //receive message
    channel.basicConsume("ack", false, deliverCallback, consumerTag-> {
    });
}

The results are as follows, 5 messages are printed:
image.png
It can be seen from the web console that ready is 0 and unacked is 5, that is, the number of unacknowledged messages is 5.
image.png
Stop the application, that is, close the connection between the consumer and rabbitmq, the web console is as follows, and the five unacked data are back to ready.
image.png
In summary, when autoAck is false, the message is divided into two parts, one is not released to consumers(ready), and the other is delivered to consumers but not confirmed. If the unconfirmed consumer disconnects, this part of the message will return to ready to be delivered to the consumer again, ensuring the reliability of the message. It should be noted that if the consumer has not disconnected or confirmed, the message will be waiting for confirmation.

confirm

There are two kinds of confirmation, one is automatic confirmation, and the other is manual confirmation. For automatic confirmation, set autoAck to true.
When rabbitmq delivers messages to consumers, it will carry a delivery tag for deliveryTag. The tag uniquely identifies the delivery on the channel. The scope of the delivery tag is each channel, so it must be confirmed on the channel receiving the message. The delivery token is an increasing positive integer, so we see that it is an increasing number like 1,2,3.
In the above example, there is a line of code commented for manual confirmation. The first parameter is the transfer flag, and the second parameter is whether to batch confirm.
The printout above outputs the value of deliveryTag, from 1 to 5. After deleting the comment and then running, you can see rabbitmq delete the confirmed message.

void basicAck(long deliveryTag, boolean multiple) throws IOException;

Batch confirmation

In the basicAck method, one parameter is multiple, which is used for batch confirmation. When set to true, RabbitMQ will confirm all outstanding transfer marks, including the mark specified in the confirmation. As with other content related to confirmation, this is determined for each channel. For example, if you receive no confirmation marked 1, 2 and confirmation marked 3, then the first two will also be confirmed together.
Let's take a look at the following example, acknowledging every three messages processed.

public static void main(String []args) throws IOException, TimeoutException {
    //Declare a connection factory
    ConnectionFactory factory = new ConnectionFactory();
    //Create a connection to the rabbitmq server
    Connection connection = factory.newConnection();
    //Create a Channel
    Channel channel = connection.createChannel();
    //Define the queue through Channel
    channel.queueDeclare("multiple", false, false, false, null);
    //Asynchronous callback processing
    DeliverCallback deliverCallback =(consumerTag, delivery)-> {
        String message = new String(delivery.getBody(), "UTF-8");
        System.out.println("multiple Received '" + message + "'" + delivery.getEnvelope(). GetDeliveryTag());
        if(delivery.getEnvelope(). getDeliveryTag()%3 == 0) {
            channel.basicAck(delivery.getEnvelope(). getDeliveryTag(), true);
        }
    };
    //receive message
    channel.basicConsume("multiple", false, deliverCallback, consumerTag-> {
    });
}

After starting, send two messages, you can see it printed twice
image.png
The console shows 2 unconfirmed
image.png
Send another piece of data and print the third
image.png
The web console sees that the queue message has been confirmed and deleted
image.png

Which confirmation method to use

Automatic confirmation, this mode is usually called "forget and forget". When the consumer handles an exception, the message sent by the server will not be processed correctly. Therefore, automatic message confirmation should be considered insecure.
In manual confirmation mode, message prefetching is usually used, which limits the number of outstanding("in progress") deliveries on the channel. However, there is no such limit for automatic confirmation, so consumers may process the message too slowly, resulting in memory backlog and heap exhaustion, resulting in the program unable to run. Therefore, the automatic confirmation mode is only suitable for consumers who can efficiently and stably handle delivery.