4. RabbitMQ消息传递的可靠性保证:ConfirmCallback、returnCallback、手动确认

如何保证消息的可靠性

消息的可靠性需要两个方面来保证:

1. 生产者 -> 队列 (可靠投递)
2. 队列 -> 消费者 (可靠消费)

1. 可靠投递

生产者 -> 队列 需要经过两步:
1. 生产者 到 交换机
2. 交换机 到 队列
只要保证这两步的可靠传递就可以保证 消息的可靠投递了

1.1 生产者到交换机的可靠保证

生产者到交换机的可靠保证依靠的是: confrimCallback 机制。

confirmCallbake 翻译过来也就是确认回调。默认是不开启的
当开启这个模式之后,生产者个交换机发送一个消息,交换机收到这个消息之后,
会给消费者发送一个确认收到的信息。

在配置文件中开启 confirmCallback,这里采用yml文件

spring:
  rabbitmq:
    publisher-confirm-type: correlated # 开启confirmCallback

这是使用Junit4 测试方法发送一个消息进行测试

@Test
void testConfirmCallBack(){
    // 设置ConfimCallball, 重写其中的 confim方法
    rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
			/* 
			 ack 表示消息是否到达了交换机,交换机是否确认收到消息
			 cause 存储的是没有到达交换机的原因
			*/
            if(ack==false){
                System.out.println("如果没有到达交换机,根据需要写你的业务代码");
            }
        }
    });

    Map<String,Object> message=new HashMap<>();
    message.put("product_id",10);
    message.put("num",50);
    message.put("price",600);
    rabbitTemplate.convertAndSend("abc","hello.orange.abc", JSON.toJSONString(message));
}

1.2 交换机到队列的保证机制

采用 returnCallback 机制,默认不开启


returnCallback 翻译过来就是返回回调,但是这种回调机制并不像 confirmCallback 机制一样,
confirmCallback 不管消息是否成功到达交换机都会被调用,
returnCallback 只有在交换机到达队列失败的时候才会被触发,当这个回调函数被调用的时候,
说明交换机的消息没有顺利的到达队列

在配置文件中开启returnCallback 机制,这里使用yml文件

spring:
  rabbitmq:
    publisher-returns: true # 开启returnCallback

测试代码:

@Test
void testReturnCallBack(){
    // 为rabbitTemplate设置return机制触发的方法
    rabbitTemplate.setReturnsCallback(messgae->{
        System.out.println(messgae);
    });
    Map<String,Object> message=new HashMap<>();
    message.put("product_id",10);
    message.put("num",50);
    message.put("price",600);
    rabbitTemplate.convertAndSend(
        RabbitConfiguration.exchange_name01, // 交换机名称
        "das", // routingKey
        JSON.toJSONString(message));//要发送的消息
}

2. 保证消息到达消费者的可靠性

消息安全的到达消息队列之后,当它被消费者消费的时候,可能也会发生不可靠的传递。
还有就是之前采用的是自动确认模式,这时候如果消费者这边出现了一些问题,而消息队列那边以为消费者成功处理了,把消息给丢弃掉了,这时候也会有一些问题。这时候推荐使用手动确认模式
默认使用的是auto模式,需要配置使用手动确认

2.1 使用手动确认模式保证消费可靠

在配置文件中开启手动确认模式,这里使用yml文件

spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: manual # 使用手动确认模式

测试代码

@Component
public class MyListener {
    @RabbitListener(queues = {"springboot-topic-queue01"})
    public void message(Message message, Channel channel) throws  Exception{
        //接受消息
        System.out.println(message.getBody());
        try {
            System.out.println("业务处理");
            // 没有出现异常,手动确认该消息,消息队列会删除该消息
            channel.basicAck(
            		/// 获取消息的传送标签,queue使用该标签进行确认消息
                    message.getMessageProperties().getDeliveryTag(),
                    false // 是否把之前的消息全都确认。
            );
        }catch (Exception e){
            // 如果出现异常,不确认该消息
            channel.basicNack(
                    message.getMessageProperties().getDeliveryTag(),
                    false, // 是否确认多条
                    false // 是否重新发送
            );
        }
    }
}

消息可靠性总结:

1. 持久化:
		- exchange 持久化
		- queue 持久化
		- message 持久化
2. 生产者 -> 交换机 confirmCallback
3. 交换机 -> 队列 returnCallback
4. 队列 -> 消费者 手动确认
5. 还可以使用集群,防止Broker宕机

做到这些还是可能会有其他情况:
例如:消息的重复消费等
可以看这一篇:设计层面的消息可靠性保证:消息补偿、消息幂等性保障

  • 7
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值