【SpringBoot】整合RabbitMQ 消费者确认模式

文章介绍了在SpringBoot应用中配置RabbitMQ消费者的方法,包括导入相关依赖,设置YML文件中的RabbitMQ连接信息。重点讨论了消息确认机制,包括自动确认和手动确认的差异。在自动确认模式下,消息接收后即被确认,可能导致异常时消息丢失。而在手动确认模式下,需在业务处理成功后调用`basicACK()`,异常时调用`basicNACK()`,确保消息可靠传递。示例代码展示了如何实现手动确认的消费者监听。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消费者端

目录结构

导入依赖

修改yml

业务逻辑

自动确认

手动确认


消费者端

目录结构

 

导入依赖

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

修改yml

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

        可以看出来listener由两种类型:direct、simple。前者用于直接交换机,而后者用于其他交换机

         可以看出自动确认模式有三种方式:none、auto、manual。

        acknowledge-mode: none 表示自动确认消息(默认值)

        acknowledge-mode: manual  表示手动确认消息

        acknowledge-mode: auto 表示根据异常情况确认消息

        自动确认是指当消息一旦被消费者接收到则自动确认收到,并将消息从RabbitMQ的消息缓存中移除。但是在实际业务当中,很可能消息接收到,业务处理出现异常,那么该消息就会丢失。如果采用了手动确认方式则需要在业务处理成功后,调用channel.basicACK(),如果出现异常则调用channel.basicNack(),让其自动重新发送消息。

业务逻辑

自动确认

/**
 * 消费者自动确认消息
 * 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()));
    }
}

手动确认

/**
 * 消费者手动确认消息
 * 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("消息被拒绝签收了");
        }
    }
}

        注意哈:上面的终端出现了死循环是因为channel.basicNack()方法的第三个参数使其消息重回队列中重新发送,但try的业务逻辑块一直有问题,所以会重复的报错,如果第三个参数是false结果如下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值