Springboot integrates rabbitmq manual AKC mechanism

Scenario: When the rabbitmq server is down, a message is being processed. At this time, the message is not processed, but no error is reported. Start MQ again and the message disappears.
Solution: Manual ACK
Manual ACK: But when our business is completed, we manually tell the queue that the queue has been completed. If you do not tell the queue, the message will always be stored in the queue.

channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);	
告诉队列已经消费完成。参数1 当前消息的索引位置,
第二个参数是否批量ACK该索引之前的消息
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
告诉队列消费失败
参数1 当前消息的索引位置 
第二个参数是否批量ACK该索引之前的消息 
第三个参数 是否重回队列 

Configuration file

server:
  port: 8093
spring:
  rabbitmq:
    host: 192.168.1.36
    port: 5672
    username: cll
    password: cll@2020
    listener:
      simple:
        retry:
          enabled: true
          multiplier: 2 #乘子 默认是1
          max-attempts: 5 #最大重试次数 默认是3
          max-interval: 20000000  #最大重试间隔 默认是10000毫秒 也就是10s
          initial-interval: 3000 # 间隔多少重试
        default-requeue-rejected: false #false 消息被拒绝以后不会重新进入队列,超过最大重试次数会进入死信队列
        acknowledge-mode: manual #默认auto
        #NONE 可以称之为自动回调,即使无响应或者发生异常均会通知队列消费成功,会丢失数据。
        #AUTO 自动检测异常或者超时事件,如果发生则返回noack,消息自动回到队尾,但是这种方式可能出现消息体本身有问题,返回队尾其他队列也不能消费,造成队列阻塞。
        #MANUAL 手动回调,在程序中我们可以对消息异常记性捕获,如果出现消息体格式错误问题,手动回复ack,接着再次调用发送接口把消息推到队尾。

Then we change the consumer code

@Component
public class DelListener {

    @RabbitListener(queues = "cme_UploadZJFace")
    public void listener(Message message, Channel channel) throws IOException {
        SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd hh mm ss");
        String s = sd.format(new Date()).toString();
        System.out.println("消费中---------------------------"+s);
        try {
            int i=1/0;
            //channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            System.out.println("消费失败---------------------------"+s);
            //channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
            e.printStackTrace();
        }
    }
    @RabbitListener(queues = "REDIRECT_QUEUE")
    public void receiveA(Message message){
        System.out.println("进入死信队列");
    }


}

Send a message to find
Insert picture description here
and then look at the MQ management page.
Insert picture description here
We find that there is a message in the queue all the time.
Then we remove the ACK and NACK comments. Start the project again.
Insert picture description here
Insert picture description hereWe will find that this message will directly enter the dead letter queue after NACK.
There will be no retrying.
Look at the management page again,
Insert picture description here
and then we are trying other cath exception information and
replace it with IO exception

@RabbitListener(queues = "cme_UploadZJFace")
public void listener(Message message, Channel channel) throws IOException {
    SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd hh mm ss");
    String s = sd.format(new Date()).toString();
    System.out.println("消费中---------------------------"+s);
    try {
        int i=1/0;
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    } catch (IOException e) {
        System.out.println("消费失败---------------------------"+s);
        channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
        e.printStackTrace();
    }
}

Insert picture description here
The console information found that it did not retry 5 times, but did not enter the dead letter queue.
It turns out that if we configure manual acknowledgment, then we will only acknowledge the message with manual ACK, and manual NACK will enter the dead letter queue.

Guess you like

Origin blog.csdn.net/ChenLong_0317/article/details/105416126