rabbitMQ-消费者手动确认-ACK

1、消费者消费消息

如果我们设置的是自动确认的话,那么就会有当接收到消息,去处理消息的时候生成异常,那么就会有消息丢失的情况。

所以我们可以设置手动确认

2、springBoot设置手动确认消息

2.1引入依赖

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

2.2application.yml配置开启自动手动确认

spring:
  application:
    name: rabbitmq-springboot
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: ems
    password: 123
    virtual-host: /ems
    # 发送者开启 confirm 确认机制
    publisher-confirm-type: simple
    # 发送者开启 return 确认机制
    publisher-returns: true
    listener:
      simple:
        # 设置消费端手动 ack
        acknowledge-mode: manual
        # 是否支持重试
        retry:
          enabled: true


server:
  port: 7071

2.3消费者代码实现

package com.lst.hello;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class WorkCustomer {
    @RabbitListener(queues = "TestQueue")

    @RabbitHandler
    public void processHandler(String msg, Channel channel, Message message) throws IOException {

        try {

            System.out.println("收到消息"+msg);
            int i = 1/0;
            System.out.println("确认消息");
            //手动签收
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        }  catch (Exception e) {
            //是否是重新回到队列的消息
            //这里有一个问题就是,代码错误的话回无限的重新接受消息,从而是cup急剧上升
            System.out.println("消息即将再次返回队列处理...");
            //b:是否允许多条处理  b1:是否重新回到队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);

        }
    }

}

2.4生产者代码 (上一篇博客)

rabbitMQ-生产者可靠发送-回退模式-return

2.5测试结果

3、问题

业务代码一旦出现BUG,多数情况不会自动修复,一条消息会被无限投递进队列,消费端一直接受处理--->然后处理失败--->重新回到队列,导致了死循环。

解决思路

1、 将失败的消息拒绝之后,重新发送到队列的尾部,这样可以保证其他的正常的消息是可以被处理的。

//确认消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
//channel对象重新发送消息到队尾
channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
                    message.getMessageProperties().getReceivedRoutingKey(), MessageProperties.PERSISTENT_TEXT_PLAIN,
                    JSON.toJSONBytes(msg));

2、设置消息重试次数,达到了重试上限以后,队列删除此消息,并将消息持久化到数据库并推送报警,然后人工处理和定时任务补偿。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用Spring Boot集成RabbitMQ时,可以使用手动确认模式来确保消息被正确处理。手动确认模式通过调用channel.basicAck方法来确认消息的处理结果。如果手动确认无效,可能是由于以下几个原因: 1. 消费者没有配置正确的ack模式:在RabbitMQ配置中,可以使用在@RabbitListener注解中设置ackMode属性来指定确认模式。常见的确认模式有NONE、AUTO、MANUAL三种。确保消费者确认模式设置为MANUAL。 2. 消费者没有正确地处理消息:在消费者代码中,确保消息的处理结果正确返回,并在处理完成后调用channel.basicAck方法进行手动确认。如果消息处理抛出异常或者没有调用basicAck方法,消息会被认为是未处理完成,RabbitMQ会将消息重新分发给其他消费者。 3. 消息被重新入队列:如果消息被重新入队列,可能会导致手动确认无效。在处理消息过程中,如果消费者抛出了异常或者手动拒绝了消息,RabbitMQ会将消息重新放回队列。确保在处理消息过程中没有发生异常,并且手动拒绝消息时设置requeue参数为false,确保消息不会重新入队列。 4. RabbitMQ服务配置问题:检查RabbitMQ服务器的配置,确保可靠性模式设为ACK。如果服务端配置的不正确,可能导致消费者手动确认无效。 总之,如果手动确认无效,需要仔细检查消费者确认模式、消息处理过程中的异常处理、消息的手动拒绝和确认操作等方面,同时确保RabbitMQ服务器的配置正确。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值