RabbitMQ备份交换机
备份交换机介绍
注:回退消息和备份交换机有一个即可,两个存在备份交换机的优先级高
有了mandatory 参数和回退消息,我们获得了对无法投递消息的感知能力,有机会在生产者的消息无法被投递时发现并处理。但有时候,我们并不知道该如何处理这些无法路由的消息,最多打个日志,然后触发报警,再来手动处理。而通过日志来处理这些无法路出的消息是很个B(得HBmMandator参教会增所在的服务有多台机器的时候,手动复制日志会更加林观而且谷易出诺。Eg自“7不想相增加生产者的加生产者的复杂性,需要添加处理这些被退回的消息的逻辑。刘如未既个怎去旧盾r信交换机来存储那些复杂性,该怎么做呢?前面在设置死信队列的文章中,我们提到,可以为队列设置死信交换机来存储那些处理失败的消息,可是这些不可路由消息根本没有机会进入到队列,因此无法使用死信队列来保存消息。
在RabbitMQ.中,有一种备份交换机的机制存在,可以很好HMX人个挽机明一个对应的备份交换机时,交换机可以理解为RabbitMQ中交换机的“备胎”,当我们为呆一个父换从网自一5多份交换机中,由就是为它创建一个备胎,当交换机接收到一条不可路由消息时,将会把这亲消息I友到自讯好读孔与其绑备份交换机来进行转发和处理,通常备份交换机的类型为Fanout,这样就能把所有消息都投递到与其绑定的队列中,然后我们在备份交换机下绑定一个队列,这样所有那些原交换机无法被路由的消息,就会都进入这个队列了。当然,我们还可以建立一个报警队列,用独立的消费者来进行监测和报警。
备份交换机架构图

RabbitMQ备份交换机(配置类)
修改ConfirmConfig配置类
package com.springbootrabbitmq.config;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 配置类 发布确认 (高级)
*/
@Configuration
public class ConfirmConfig {
//交换机
public static final String CONFIRM_EXCHANGE_NAME = "confirm_exchange";
//队列
public static final String CONFIRM_QUEUE_NAME = "confirm_queue";
//RoutingKey
public static final String CONFIRM_ROUTING_KET_="key1";
//备份交换机
public static final String BACKUP_EXCHANGE_NAME = "backup_exchange";
//备份队列
public static final String BACKUP_QUEUE_NAME="backup_queue";
//报警队列
public static final String WARNIGN_QUEUE_NAME="warngin_queue";
//声明交换机
@Bean("confirmExchange")
public DirectExchange confirmExchange(){
//无法投递消息发送给备份交换机
return ExchangeBuilder.directExchange(CONFIRM_EXCHANGE_NAME).durable(true)
.withArgument("alternate-exchange",BACKUP_EXCHANGE_NAME).build();
}
@Bean("confirmQueue")
public Queue confirmQueue() {
return QueueBuilder.durable(CONFIRM_QUEUE_NAME).build();
}
//备份交换机
@Bean("backupExchange")
public FanoutExchange backupExchange(){
return new FanoutExchange(BACKUP_EXCHANGE_NAME);
}
@Bean("backupQueue")
public Queue backupQueue(){
return QueueBuilder.durable(BACKUP_QUEUE_NAME).build();
}
@Bean("warnginQueue")
public Queue warnginQueue(){
return QueueBuilder.durable(WARNIGN_QUEUE_NAME).build();
}
//绑定
@Bean
public Binding queueBindingExchange(@Qualifier("confirmQueue") Queue confirmQueue,
@Qualifier("confirmExchange") DirectExchange confirmExchange){
return BindingBuilder.bind(confirmQueue).to(confirmExchange).with(CONFIRM_ROUTING_KET_);
}
//备份绑定
@Bean
public Binding backupBindingExchange(@Qualifier("backupQueue") Queue backupQue,
@Qualifier("backupExchange") FanoutExchange backupExchange){
return BindingBuilder.bind(backupQue).to(backupExchange);
}
@Bean
public Binding warnginQueueBindingExchange(@Qualifier("warnginQueue") Queue warnginQueue,
@Qualifier("backupExchange") FanoutExchange backupExchange){
return BindingBuilder.bind(warnginQueue).to(backupExchange);
}
}
在浏览器删除rabbitmq中的确认交换机:confirm_exchange
RabbitMQ备份交换机(报警消费者)
由于以写过Consumer确认交换机所有不要写只要写报警消费者即可
package com.springbootrabbitmq.consumer;
import com.springbootrabbitmq.config.ConfirmConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 报警消费者
*/
@Component
@Slf4j
public class WarningConsumer {
//接收报警消息
@RabbitListener(queues = ConfirmConfig.WARNIGN_QUEUE_NAME)
public void receiveWaringMessage(Message message){
String msg = new String(message.getBody());
log.error("报警发现不可路由消息:{}",msg);
}
}
mandatory参数与备份交换机可以一起使用的时候,如果两者同时开启,消息究竟何去何从?谁优先级高,经过上面结果显示答案是备份交换机优先级高。