0.回顾
Spring Boot RabbitMQ 入门(二) 环境搭建
上篇文章我们学习了以下几点:
* 1.如何创建交换器
* 2.如何创建对列
* 3.如何将队列绑定到交换器
* 4.如何创建消费者
1.Exchange功能介绍
交换器的作用:当你想将消息投递到对列的时候,你通过把消息交给交换器,通过交换器匹配一些规则,根据这些规则RabbitMQ知道将消息投递到哪个队列。这些规则就是路由键,对列是通过路由键绑定到交换器的。当你将消息发送到代理服务器时,消息将拥有一个路由键,即便是空的,RabbitMQ也会将其与绑定使用的路由键进行匹配,如果匹配成功则消息会投入到消息对列。反之则消息将进入“黑洞”,被丢弃。
2.Fanout路由原理
fanout路由又称为广播路由,这种路由会将收到的消息广播到消息对列上。如上图所示,即当使用fanout交换器时,他会将消息广播到与该交换器绑定的所有队列上,这有利于你对单条消息做不同的反应。
例如存在以下场景:一个web服务要在用户完善信息时,获得积分奖励,这样你就可以创建两个对列,一个用来处理用户信息的请求,另一个对列获取这条消息是来完成积分奖励的任务。
3Fanout路由模拟
代码部分如果不清楚的可以看上一篇
Spring Boot RabbitMQ 入门(二) 环境搭建
3.1创建Fanout交换器
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(EXCHANGE);
}
3.2创建两个对列
@Bean
public Queue queue() {
return new Queue("spring-queue", true); //队列持久
}
@Bean
public Queue queue2() {
return new Queue("spring-queue2", true); //队列持久
}
3.3将两个对列绑定到Fanout交换器
@Bean
public Binding binding() {
return BindingBuilder.bind(queue()).to(fanoutExchange());
}
@Bean
public Binding binding2() {
return BindingBuilder.bind(queue2()).to(fanoutExchange());
}
3.4定义消费者分别消费对列1,2
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(queue());
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(1);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
byte[] body = message.getBody();
System.out.println("receive msg b: " + new String(body));
Thread.sleep(30000);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
}
});
return container;
}
@Bean
public SimpleMessageListenerContainer messageContainer2() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(queue2());
container.setExposeListenerChannel(true);
container.setMaxConcurrentConsumers(1);
container.setConcurrentConsumers(1);
container.setAcknowledgeMode(AcknowledgeMode.MANUAL); //设置确认模式手工确认
container.setMessageListener(new ChannelAwareMessageListener() {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
byte[] body = message.getBody();
System.out.println("receive msg a: " + new String(body));
Thread.sleep(30000);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); //确认消息成功消费
}
});
return container;
}
并且将收到的消息打印出来,如果打印结果是消息创建投递到fanout交换器时两个对列都收到了则表示,证明了上述结论。
3.5创建消息生产者
配置文件
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate(){
RabbitTemplate template =new RabbitTemplate(connectionFactory());
return template;
}
用生产者发送消息
@Component
public class Sender implements RabbitTemplate.ConfirmCallback {
@Autowired
RabbitTemplate template;
public void send(String context) {
template.convertAndSend(RabbitConfig.EXCHANGE, "", context);
}
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
System.out.println(" 回调id:" + correlationData);
if (b) {
System.out.println("消息成功消费");
} else {
System.out.println("消息消费失败:" + s);
}
}
}
4.结论
我们发送者发送100条消息,来查看绑定在两个对列上的消费者是否都收到消息。
receive msg b: 55hello
receive msg a: 55hello
receive msg b: 56hello
receive msg a: 56hello
receive msg b: 57hello
receive msg a: 57hello
receive msg b: 58hello
receive msg a: 58hello
也验证了以上结论。