Spring Boot 整合 RabbitMQ 消息确认机制

1. 消息确认机制

在使用RabbitMQ的时候,可能会出现消息丢失的情况,这个时候就需要使用消息确认机制来保证消息的可靠生产和可靠消费

生产端消息确认:

​ ConfirmCallback:消息从生产端到交换机触发该回调函数 (无论成功或失败)
​ ReturnsCallback:消息从交换机到到队列触发该回调函数(消息发送失败)

消费端消息确认:

​ 手动ACK进行确认

2. 生产端消息确认
2.1 配置文件
spring:
  rabbitmq:
    # 开启confirm消息发送回调函数
    publisher-confirm-type: correlated
    # 开启return确认模式
    publisher-returns: true
2.2 代码示例
/**
 * @author: mingan.xie
 * @since: 2021/3/31
 * @history: 1.2021/3/31 created by xma
 */
@Component
public class RabbitMQSendCallback implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void run() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * 消息发动到交换机时的回调函数
     *
     * @param correlationData
     * @param b     如果消息发送成功则为true, 反之为false
     * @param s 消息体
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean b, String s) {
        if (!b) {
            System.out.println("消息发送成功");
        } else {
            System.out.println("消息发送失败,进行容错处理");
        }
        System.out.println("消息发动到交换机时的回调函数, ack:" + b + "  消息体:" + s);
    }

    /**
     * 消息从交换机发送到队列时的回调函数
     * 如果发送成功则不回调该函数, 反之则回调
     *
     * @param returnedMessage
     */
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        System.out.println("消息从交换机发送到队列时的回调函数, 调用失败!!!");
    }
}
3. 消费端消息确认

解决方案:

​ 控制重发次数 + 死信队列处理 (注意需要抛出异常,不能try…catch,否则会陷入死循环)

​ try…catch + 手动Ack + 人工干预(示例为此种方案)

​ try…catch + 手动Ack + 死信队列

3.1 配置文件
spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1 #限制每次只发送一条消息,防止多个通道消息积压过多导致服务崩溃
        acknowledge-mode: manual #采用手动应答方式
#        etry:
#          #重试次数5(重新投递次数)
#          max-attempts: 5r
3.2 代码示例
/**
 * @author: mingan.xie
 * @since: 2021/3/29
 * @history: 1.2021/3/29 created by xma
 */
@Component
@RabbitListener(queues = {"duanxin.direct.queue"})
public class DirectDuanxinConsumer {
    
    
    @RabbitHandler
    public void reviceMessage(String message, Channel channel, Message message1){
        try {
            System.out.println("direct Duanxin 接收到了消息:" + message);
            // 手动ack, 进行消息确认机制
            //      deliveryTag:该消息的index
            //      multiple:是否批量. true:将一次性ack所有小于deliveryTag的消息
            channel.basicAck(message1.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
                /**
                 * 拒绝确认消息
                 * deliveryTag:该消息的index
                 * multiple:是否批量.true:将一次性拒绝所有小于deliveryTag的消息
                 * requeue:被拒绝的是否重新入队列
                 *      true:重新进入队列并进行消费,可以配合自己定义的重试次数(非spring配置)进行处理
                 *      false:丢弃该消息,可以配合死信队列进行处理
                 */
            try {
                channel.basicNack(message1.getMessageProperties().getDeliveryTag(),false, false);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值