一、介绍
备份交换器,英文名字为Alternate Exchange, 简称AE。我们知道有这样一个参数,mandatory。当这个参数为false时,如果投放消息时没有找到指定的路由键,消息就会直接丢弃。而当这个参数为
true时,如果消息不会直接丢弃,而是将其返回生产者,而这样需要在生产者里添加一些代码。
我们不想复杂生产者的编程逻辑,同时又不想消息丢失就可以使用AE。
二、配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
下面时yml文件
server:
port: 8080
spring:
application:
name: provider-with-alternate
rabbitmq:
port: 5673
username: admin
password: admin
host: 192.168.136.128
mq:
provider:
alternate:
alternate1: myAlternate
exchange:
exchange1: myExchange
queue:
queue1: myQueue1
queue2: myQueue2
routing:
routing1: myRouting1
routing2: myRouting2
三、代码部分
收首先时配置类
package com.my;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class Config {
@Autowired
private Environment env;
@Bean
public Queue myQueue1(){
return new Queue(env.getProperty("mq.provider.queue.queue1"), true);
}
@Bean
public Queue myQueue2(){
return new Queue(env.getProperty("mq.provider.queue.queue2"), true);
}
@Bean
public FanoutExchange alternateExchange(){
return new FanoutExchange(env.getProperty("mq.provider.alternate.alternate1"),true,false);
}
@Bean
public DirectExchange directExchange(){
Map<String, Object> args = new HashMap<>();
//args 参数第一个是alternat-exchange是就是说明要使用备份交换器,第二个参数是交换器的名字
args.put("alternate-exchange", env.getProperty("mq.provider.alternate.alternate1"));
return new DirectExchange(env.getProperty("mq.provider.exchange.exchange1"), true, false, args);
}
@Bean
public Binding bindingAlternate(){
return BindingBuilder.bind(myQueue2()).to(alternateExchange());
}
@Bean
public Binding bindDirecExchange(){
return BindingBuilder.bind(myQueue1())
.to(directExchange())
.with(env.getProperty("mq.provider.routing.routing1"));
}
}
这里面有一点要说的是备份交换器一般是使用fanout类型的交换器。
发送逻辑如下
package com.my;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class Sender {
@Autowired
RabbitTemplate rabbitTemplate;
@Autowired
Environment env;
public void send(){
rabbitTemplate.convertAndSend(env.getProperty("mq.provider.exchange.exchange1"),
env.getProperty("mq.provider.routing.routing1"),
"hello! direct exchange");
rabbitTemplate.convertAndSend(env.getProperty("mq.provider.exchange.exchange1"),
env.getProperty("mq.provider.routing.routing2"),
"hello! alternate exchange");
}
}
上面的逻辑中,routing1是与direct交换机绑定的键,而routing2没有绑定,这样我们发送消息后就可以看出queue1和queue2中同时出现了消息。
最后是controller
package com.my;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@Autowired
private Sender sender;
@GetMapping("/send")
public String send(){
sender.send();
return "ok";
}
}
三、结果
我们可以看出两个队列消息数量相等。