RabbitMQ高级-消息确认机制的配置

1、正常情况下能正常接收

1、创建交换机、队列、绑定交换机和 队列

package com.sky.config;

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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 尹稳健~
 * @version 1.0
 */
@Configuration
public class ConfirmRabbitMQConfig {

    // 声明交换机
    @Bean
    public DirectExchange confirmExchange(){
        return new DirectExchange("confirm_exchange",true,false);
    }

    // 声明队列
    @Bean
    public Queue confirmQueue(){
        return new Queue("confirm_queue",true);
    }

    // 绑定交换机和队列
    @Bean
    public Binding confirmQueueBind(){
        return BindingBuilder.bind(confirmQueue()).to(confirmExchange()).with("confirm");
    }
}

2、发送消息

public void makeOrderConfirm(String userId, String productId, int num) {
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "confirm_exchange";
    String routeKey = "confirm";
    rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success");
}

3、测试

在这里插入图片描述

2、交换机发生故障的情况下如何发现消息没有发送过去

1、创建交换机和队列

同上。略。

2、创建配置类

当消息没有被确认时,执行回调方法,这个回调方法需要手动应答

package com.sky.config;

import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author 尹稳健~
 * @version 1.0
 * 回调接口
 */
@Configuration
public class MyCallBack implements RabbitTemplate.ConfirmCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 因为是RabbitTemplate的内部接口,所以需要注入
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
    }

    // 交换机确认回调方法
    /**
     *
     * @param correlationData    消息的相关信息
     * @param ack     是否确认消息
     * @param cause     错误的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (!ack){
            System.out.println("交换机没有收到信息:"+correlationData.getId()+",原因是:"+cause);
            System.out.println("接收失败!");
        }else{
            System.out.println("接收成功!");
        }
    }
}

3、编写yml配置

server:
  port: 8080

spring:
  # RabbitMQ配置
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: admin
    virtual-host: /
    # 确认消息回调方法
    publisher-confirm-type: correlated

4、发送消息故意将交换机名称写错

public void makeOrderConfirm(String userId, String productId, int num) {
    String orderId = UUID.randomUUID().toString();
    CorrelationData correlationData = new CorrelationData();
    correlationData.setId("1");
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "confirm_exchange";
    String routeKey = "confirm";
    rabbitTemplate.convertAndSend(exchangeName+"1",routeKey,orderId+"----success",correlationData);
    rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}

5、测试

在这里插入图片描述

报错,交换机不存在,接受失败

3、交换机能接受到消息,但是队列无法接受到消息,那么怎么让消息回退到交换机中去呢?

1、创建交换机、队列、绑定交换机

同上、略。

2、编写配置类

因为RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback是RabbitTemplate中的内部接口,所以调用之前需要注入。

package com.sky.config;

import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * @author 尹稳健~
 * @version 1.0
 * 回调接口
 */
@Configuration
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 因为是RabbitTemplate的内部接口,所以需要注入
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }

    // 交换机确认回调方法
    /**
     *
     * @param correlationData    消息的相关信息
     * @param ack     是否确认消息
     * @param cause     错误的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (!ack){
            System.out.println("交换机没有收到信息:"+correlationData.getId()+",原因是:"+cause);
            System.out.println("接收失败!");
        }else{
            System.out.println("接收成功!");
        }
    }

    // 消息回退
    // 只有不可到达目的地的时候才会回退
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        System.out.println(returnedMessage.getMessage()+
                "消息发送失败,退回交换机"+returnedMessage.getExchange());
    }
}

3、编写yml配置

server:
  port: 8080

spring:
  # RabbitMQ配置
  rabbitmq:
    host: localhost
    port: 5672
    username: admin
    password: admin
    virtual-host: /
    # 确认消息回调方法
    publisher-confirm-type: correlated
    # 退回消息
    publisher-returns: true

4、发送消息,故意将队列名称写错

public void makeOrderConfirm(String userId, String productId, int num) {
    String orderId = UUID.randomUUID().toString();
    CorrelationData correlationData = new CorrelationData();
    correlationData.setId("1");
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "confirm_exchange";
    String routeKey = "confirm";
    rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success",correlationData);
    rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}

5、测试

在这里插入图片描述

注意这里消息发送失败了,退回到交换机中了。

下面的接收成功是交换机接收成功,不是队列!

4、备份交换机

备份交换机,用来备份交换机发送队列的失败消息。

备份交换机中有2各队列:一个是备份消息的队列还有一个是预警队列

// 这里因为是要备份所以使用这种方式创建
​ return ExchangeBuilder.directExchange(“confirm_exchange”)
​ .withArgument(“alternate-exchange”,“backup_exchange”).build();

1、创建交换机和队列 绑定

package com.sky.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 尹稳健~
 * @version 1.0
 */
// 备份交换机 和 备份队列  报警队列
@Configuration
public class BackRabbitMQConfig {

    // 声明交换机
    @Bean
    public FanoutExchange backupExchange(){
        return new FanoutExchange("backup_exchange");
    }

    // 声明队列
    @Bean
    public Queue backupQueue(){
        return new Queue("backup_queue",true);
    }

    @Bean
    public Queue warningQueue(){
        return new Queue("warning_queue",true);
    }

    // 绑定交换机和队列
    @Bean
    public Binding backupBinding(){
        return BindingBuilder.bind(backupQueue()).to(backupExchange());
    }

    @Bean
    public Binding warningBinding(){
        return BindingBuilder.bind(warningQueue()).to(backupExchange());
    }

}
package com.sky.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 尹稳健~
 * @version 1.0
 */
@Configuration
public class ConfirmRabbitMQConfig {

    // 声明交换机
    @Bean
    public DirectExchange confirmExchange(){
        // 这里因为是要备份所以使用这种方式创建
        return ExchangeBuilder.directExchange("confirm_exchange")
                .withArgument("alternate-exchange","backup_exchange").build();
    }

    // 声明队列
    @Bean
    public Queue confirmQueue(){
        return new Queue("confirm_queue",true);
    }

    // 绑定交换机和队列
    @Bean
    public Binding confirmQueueBind(){
        return BindingBuilder.bind(confirmQueue()).to(confirmExchange()).with("confirm");
    }


}

2、发送消息(一条正确的和一条错误的)

public void makeOrderConfirm(String userId, String productId, int num) {
    String orderId = UUID.randomUUID().toString();
    CorrelationData correlationData = new CorrelationData();
    correlationData.setId("1");
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "confirm_exchange";
    String routeKey = "confirm";
    rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId+"----success",correlationData);
    rabbitTemplate.convertAndSend(exchangeName,routeKey+"1",orderId+"-----false",correlationData);
}

3、测试

在这里插入图片描述

在这里插入图片描述

接收后:

在这里插入图片描述

返回报警队列中的消息,和一条发送正确的消息


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕竟尹稳健

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值