RabbitMQ------消息可靠性投递

一。什么是消息可靠性投递?

1.保证消息百分百发送到消息队列中去
a.保证mq节点成功接受消息
b.消息发送端需要接受到mq服务端接受到消息的确认应答

c.完善的消息补偿机制,发送失败的消息可以再感知并二次处理

 

二。RabbtiMQ消息投递路径

1.生产者-->交换机->队列->消费者

2.通过两个的点控制消息的可靠性投递
a.生产者到交换机
  通过confirmCallback
b.交换机到队列
  通过returnCallback

3.建议
开启消息确认机制以后,保证了消息的准确送达,但由于频繁的确认交互, rabbitmq 整体效率变低,吞吐量下降严重,不是非常重要的消息真心不建议用消息确认机制

 

三。生产者到交换机

1.通过confirmCallback实现

2.生产者投递消息后,如果Broker收到消息后,会给生产者一个ACK。生产者通过ACK,可以确认这条消息是否正常发送到Broker,这种方式是消息可靠性投递的核心

3.开启confirmCallback

#旧版,确认消息发送成功,通过实现ConfirmCallBack接口,消息发送到交换器Exchange后触发回调

spring.rabbitmq.publisher-confirms=true

#新版,NONE值是禁用发布确认模式,是默认值,CORRELATED值是发布消息成功到交换器后会触发回调方法

spring.rabbitmq.publisher-confirm-type: correlated

代码:

部分代码可参考:

https://www.cnblogs.com/tianhengblogs/p/15341670.html

//测试消息回调确认
    @GetMapping("/confirm")
    public String testConfirm(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             * @Description
             * @param correlationData 配置
             * @param ack 交换机是否接收到消息 true: 成功  false: 失败
             * @param cause 失败原因
             * @return
             */
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                //判断
                if (ack){
                    //更新数据库,消息状态为成功 TODO
                }else {
                    //更新数据库,消息状态为失败 TODO
                }

                //打印信息
                System.out.println("correlationData: " + correlationData);
                System.out.println("ack: " + ack);
                System.out.println("cause: " + cause);
            }
        });
        //数据库新增一条消息记录,状态为发送 TODO

        //发送消息
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_NAME, "order.new", "新订单消息");
        //模拟异常
        //rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_NAME + "123", "order.new", "新订单消息");
        return "success";
    }
View Code

 

四。交换机到队列

1.通过returnCallback

2.消息从交换器发送到对应队列失败时触发

3.两种模式

a.交换机到队列不成功,则丢弃消息(默认)

b.交换机到队列不成功,返回给消息生产者,触发returnCallback

4.开启returnCallback

//为true,则交换机处理消息到路由失败,则会返回给生产者
template.setMandatory(true);
//或者配置文件旧版本
spring.rabbitmq.template.mandatory=true
//新版本
spring.rabbitmq.publisher-returns=true

代码:

部分代码可参考:

https://www.cnblogs.com/tianhengblogs/p/15341670.html

@GetMapping("return")
    public String testReturn(){
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                //打印信息
                System.out.println("message: " + message.toString());
            }
        });
        //发送消息
//        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_NAME, "order.new", "新订单消息");
        //模拟异常
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_NAME, "123.order.new", "新订单消息");
        return "success";
    }
View Code

 

posted @ 2021-09-27 11:34  玉天恒  阅读(146)  评论(0编辑  收藏  举报