[SpringBoot] Integrate RabbitMQ consumer confirmation mode

consumer side

Directory Structure

import dependencies

Modify yml

Business logic

auto confirm

manual confirmation


consumer side

Directory Structure

 

import dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
        <version>2.5.0</version>
    </dependency>
</dependencies>

Modify yml

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
        acknowledge-mode: auto

        It can be seen that there are two types of listeners: direct and simple. The former is used for direct switches, while the latter is used for other switches

         It can be seen that there are three modes of automatic confirmation mode: none, auto, manual.

        acknowledge-mode: none means automatically acknowledge messages (default)

        acknowledge-mode: manual means to manually acknowledge the message

        acknowledge-mode: auto means to confirm the message according to the exception

        Automatic confirmation means that once the message is received by the consumer, it will automatically confirm the receipt and remove the message from RabbitMQ's message cache. However, in the actual business, it is very likely that the message is received and the business processing is abnormal, then the message will be lost. If the manual confirmation method is adopted, it is necessary to call channel.basicACK() after the business processing is successful, and if an exception occurs, call channel.basicNack() to let it automatically resend the message.

Business logic

auto confirm

/**
 * 消费者自动确认消息
 * 1、yml中需要配置acknowledge-mode: none
 * 2、消费者监听实现MessageListener 
 */
@Component
public class AckListener implements MessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message) {
        System.out.println("消费者接受的消息为:" + new String(message.getBody()));
    }
}

manual confirmation

/**
 * 消费者手动确认消息
 * 1、yml中需要配置acknowledge-mode: manual
 * 2、消费者监听实现ChannelAwareMessageListener 
 */
@Component
public class AckListener implements ChannelAwareMessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        // 消息的唯一标识id
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println("消费者接受的消息为:" + new String(message.getBody()));
            // 手动签收的第一个参数为消息的唯一标识id、第二个参数表示是否批量签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e){
            // 手动拒绝签收的第一个参数为消息id、第二个参数表示是否批量签收
            // 第三个参数消息是否重回队列
            channel.basicNack(deliveryTag,true,true);
            System.out.println("消息被拒绝签收了");
        }
    }
}

/**
 * 消费者手动确认消息
 * 1、yml中需要配置acknowledge-mode: manual
 * 2、消费者监听实现ChannelAwareMessageListener 
 */
@Component
public class AckListener implements ChannelAwareMessageListener {

    @RabbitListener(queues = "test_queue_name")
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        // 消息的唯一标识id
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println("消费者接受的消息为:" + new String(message.getBody()));
            int i = 1 / 0;//业务逻辑故意出错进入catch块
            // 手动签收的第一个参数为消息的唯一标识id、第二个参数表示是否批量签收
            channel.basicAck(deliveryTag,true);
        } catch (Exception e){
            // 手动拒绝签收的第一个参数为消息id、第二个参数表示是否批量签收
            // 第三个参数消息是否重回队列
            channel.basicNack(deliveryTag,true,true);
            System.out.println("消息被拒绝签收了");
        }
    }
}

        Note: the above terminal has an infinite loop because the third parameter of the channel.basicNack() method makes the message return to the queue for resend, but there is always a problem with the business logic block of try, so it will repeatedly report an error, if The third parameter is false and the result is as follows.

Guess you like

Origin blog.csdn.net/m0_65563175/article/details/130455209
Recommended