rabbitMQ 可靠性消息投递

目录

1.概述:

2.confirm模式代码实现:

1.加入依赖:

2.在配置文件中开启confirm模式 :

3.创建一个实现abbitTemplate.ConfirmCallback接口的实现类

4.在配置类或者启动类创建交换机,队列,绑定队列和交换机 

5.测试 :

3.return模式


1.概述:

参考(16条消息) RabbitMQ消息100%可靠性投递的解决方案实现(一)_eluanshi12的博客-CSDN博客_rabbitmq可靠性投递

可靠性消息:

在使用RabbitMQ时,作为消息发送方希望杜绝消息丢失或者投递失败的场景。RabbitMQ为我们提供了两种方式用来控制消息的投递可靠性。

confirm模式:
生产者发送消息到交换机时,使用这种模式
return模式:
交换机转发给queue时,使用这种模式

2.confirm模式代码实现

1.加入依赖:

<!--rabbitmq起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.在配置文件中开启confirm模式 :

spring:
  rabbitmq:
    port: 5672
    host: localhost
    username: guest
    password: guest
    virtual-host: /
    #开启confirms这个模式
    #springboot2.2.0.RELEASE支持这个
    #publisher-confirm-type: correlated
    publisher-confirms: true

3.创建一个实现abbitTemplate.ConfirmCallback接口的实现类

package com.example.confirm;
 
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
 
@Component
public class MyConfirmCallBack implements RabbitTemplate.ConfirmCallback {
    /**
     * 回调方法,发送消息后都会调用该方法
     * @param correlationData  数据
     * @param ack true发送成功 ,false发送失败
     * @param cause 如果是失败,那么返回这个失败原因的字符串。如果成功 原因就是null
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            //模拟在这里减100
            System.out.println("发送成功,减100成功");
        }else{
            System.out.println("发送失败,失败原因是:"+cause);
        }
    }
}

4.在配置类或者启动类创建交换机,队列,绑定队列和交换机 

package com.example;
 
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
 
@SpringBootApplication
public class Day47RabbitMqApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(Day47RabbitMqApplication.class, args);
    }
 
    //创建交换机
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("exchange_test6");
    }
    //创建队列
    @Bean
    public Queue queue(){
        return new Queue("queue_test6");
    }
    //创建绑定
    @Bean
    public Binding binding(){
        return BindingBuilder.bind(queue()).to(directExchange()).with("test6.insert");
    }
 
}

5.测试 :

测试消息发送到交换机

package com.example.controller;
 
import com.example.confirm.MyConfirmCallBack;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/testsend")
public class TestSendController {
 
    @Autowired
    private RabbitTemplate rabbitTemplate;
 
    @Autowired
    //或者用这个
    //private MyConfirmCallBack myConfirmCallBack;
    private RabbitTemplate.ConfirmCallback confirmCallback;
 
    @GetMapping ("/send1")
    public String send1(){
        //设置回调函数
        rabbitTemplate.setConfirmCallback(confirmCallback);
        //发送消息
        //rabbitTemplate.convertAndSend("exchange_test6","test6.insert","消息本身");
        //测试一个错误,没有这个交换机
        rabbitTemplate.convertAndSend("exchange_test88","test6.insert","消息本身");
        return "ok";
    }
 
}

我们测试一个错误,把交换机名称改一下,就会发现在控制台会打印错误详情。

至此我们就可以知道消息发送到交换机是否中间出现了问题,这个时候就会多一个问题,我们发现修改路由key之后,回调函授会显示消息发送成功。

所以我们需要处理交换机到路由的这个过程,消息是否转发成功。return模式。

3.return模式

完成上面的依赖以及配置后

在配置文件中开始return模式

spring:
  rabbitmq:
    port: 5672
    host: localhost
    username: guest
    password: guest
    virtual-host: /
    #开启confirms这个模式
    #springboot2.2.0.RELEASE支持这个
    #publisher-confirm-type: correlated
    publisher-confirms: true
    #开启return模式
    publisher-returns: true

然后创建一个实现类(2.2版本)实现RabbitTemplate.ReturnCallback接口:

package com.example.confirm;
 
import org.springframework.amqp.core.Message;
 
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
 
@Component
public class MyReturnCallBack implements RabbitTemplate.ReturnCallback {
    /**
     *
     * 交换机转发消息到队列时调用 , 如果成功的时候就不调用该方法了,只有转发失败的时候才调用
     * @param message     消息内容本身
     * @param replyCode   响应状态码
     * @param replyText   响应内容
     * @param exchange    交换机
     * @param routingKey   routingKey
     */
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        //获取到消息本身
        System.out.println(new String(message.getBody()));
        //message.getMessageProperties()可以获取到其他的别的信息
 
        //状态码
        System.out.println(replyCode);
 
        System.out.println(replyText);
        //exchange
        System.out.println(exchange);
        //routingKey
        System.out.println(routingKey);
 
    }
}
测试一个错误,把交换机改正确,routingKey写错
package com.example.controller;
 
import com.example.confirm.MyConfirmCallBack;
import com.example.confirm.MyReturnCallBack;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/testsend")
public class TestSendController {
 
    @Autowired
    private RabbitTemplate rabbitTemplate;
 
    @Autowired
    //或者用这个
    //private MyConfirmCallBack myConfirmCallBack;
    private RabbitTemplate.ConfirmCallback confirmCallback;
 
 
 
    @Autowired
    //private MyReturnCallBack myReturnCallBack;
    //或者用这个
    private RabbitTemplate.ReturnCallback returnsCallback;
 
    @GetMapping ("/send1")
    public String send1(){
        //设置confirm回调函数
        rabbitTemplate.setConfirmCallback(confirmCallback);
        //设置return回调函数
        rabbitTemplate.setReturnCallback(returnsCallback);
        //发送消息
        //rabbitTemplate.convertAndSend("exchange_test6","test6.insert","消息本身");
 
        //测试一个错误,把交换机改正确,routingKey写错
        rabbitTemplate.convertAndSend("exchange_test6","test6.insertxxx","消息本身");
        return "ok";
    }
}

小结:一般我们使用confirm模式就可以了,在消息发送到交换机时机去使用。一般交换机转发消息到队列不会丢失消息。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值