Fanout交换机:
现在消息的发送者先发给交换机再路由到指定的队列,不过交换机可以路由一个或者多个多种多样的队列。
Fanout可以把接收到的消息路由到与它绑定的每一个队列,相当于复制了多份,,达成了一条消息可以被多个消费者处理,fanout可以达成这种效果。
场景:我们有个业务,用户支付成功后,需要通知订单服务,通知短信服务,通知积分服务,如果用workqueque这种队列,只能被一个服务处理到,其他的都接收不到。
现在有了交换机,我们可以一个交换机绑定三个队列,每一个队列绑定一个服务,这样该三个服务消费者都能够处理该条消息,而且发送者只要发送一次,实现了一条消息就能够各自处理自己的逻辑业务
只要是跟它绑定的队列都能够发送给对方,(复制发送给所有人)
//发送方
@Test
public void testFanoutExchange() {
// 交换机名称
String exchangeName = "CSDN.fanout";
// 消息
String message = "hello, everyone!";
rabbitTemplate.convertAndSend(exchangeName, "", message);
}
//消费方 要监听的是哪个队列
@RabbitListener(queues = "fanout.queue1")
public void listenFanoutQueue1(String msg) {
System.out.println("消费者1接收到Fanout消息:【" + msg + "】");
}
@RabbitListener(queues = "fanout.queue2")
public void listenFanoutQueue2(String msg) {
System.out.println("消费者2接收到Fanout消息:【" + msg + "】");
}
这里我们一般用注解,但是为了方便理解我直接上代码了
@Configuration
public class FanoutConfigExchange {
//创建fanout交换机
@Bean
public FanoutExchange fanoutExchange()
{
return new FanoutExchange("CSDN.fanout");
}
//创建队列
@Bean
public Queue queue1()
{
// durable 持久化
return new Queue("fanout.queue1");
}
@Bean
public Queue queue2()
{
// durable 持久化
return new Queue("fanout.queue2");
}
//分别1,2队列去绑定该交换机
@Bean
public Binding fanoutbinding1(Queue queue1,FanoutExchange fanoutExchange)
{
return BindingBuilder.bind(queue1).to(fanoutExchange);
}
@Bean
public Binding fanoutbinding2(Queue queue2,FanoutExchange fanoutExchange)
{
return BindingBuilder.bind(queue2).to(fanoutExchange);
}
}
Direct 交换机:
但是我们业务需求发生变化不一定每次都需要所有的消费者都去消费该条消息,我只要部分
direct现在要求不能随便绑定,队列在创建的时候分别设置不同的Routingkey,发送者发送的时候,指定一个key,然后交换机拿到后,跟队列里的Routingkey相比较,相同就发送给队列,否则就不发给对方
以上我具体投递给谁都可以,取决于key,两个Routingkey也可以相同,两个队列同时收到,场景:假如我们用户下单,还没支付,我要取消订单,支付服务发送条消息,把我们的订单状态改为已取消,但是不用再给用户发短信了,不用再加积分了。如果业务比较复杂一点direct也比较灵活,够用
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue1"),
exchange = @Exchange(name = "CSDN.direct", type = ExchangeTypes.DIRECT),
key = {"red", "blue"}
))
public void listenDirectQueue1(String msg){
System.out.println("消费者1接收到direct.queue1的消息:【" + msg + "】");
}
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "direct.queue2"),
exchange = @Exchange(name = "CSDN.direct", type = ExchangeTypes.DIRECT),
key = {"red", "yellow"}
))
public void listenDirectQueue2(String msg){
System.out.println("消费者2接收到direct.queue2的消息:【" + msg + "】");
}
Topic交换机:
1 、将来只要是以china开头的,我都可以匹配(China.news,china.weather)
2 、将来只要是以Japan开头的,我都可以匹配(Japan.news,Japan.weather)
3 、只关心以.weather结尾的单词
4 、只关心以.news结尾的单词(下图)
优势:现在一个key可以代表多个routingKey含义,没有的话得一个个队列绑定(假如非常多个有关中国的),将来如果又出来新的key又要去绑定。以下图只要跟中国有关的都能处理,扩展性强,key的配置可以大大减少(特殊的场景,但是地保证有相同的前缀或者后缀),通常用#不用*
@RabbitListener(queues = "topic.queue1")
public void topic1(String message) throws InterruptedException {
System.out.println("fan一接收到"+message+"时间"+ LocalDateTime.now());
}
@RabbitListener(queues = "topic.queue2")
public void topic2(String message) throws InterruptedException {
System.out.println("fan二接收到"+message+"时间"+ LocalDateTime.now());
}
结果: 通过routingKey我想发给谁就发给谁
rabbitTemplate.convertAndSend("hei.topic","china.fu","hello,fufufufuufufufuf,Blue1111111111111111x");