Spring Boot RabbitMQ 入门(三)之 Fanout交换器

来源:互联网 发布:金融it行业是投行it 编辑:程序博客网 时间:2024/04/29 12:35

0.回顾


Spring Boot RabbitMQ 入门(二) 环境搭建
上篇文章我们学习了以下几点:
* 1.如何创建交换器
* 2.如何创建对列
* 3.如何将队列绑定到交换器
* 4.如何创建消费者

1.Exchange功能介绍


交换器的作用:当你想将消息投递到对列的时候,你通过把消息交给交换器,通过交换器匹配一些规则,根据这些规则RabbitMQ知道将消息投递到哪个队列。这些规则就是路由键,对列是通过路由键绑定到交换器的。当你将消息发送到代理服务器时,消息将拥有一个路由键,即便是空的,RabbitMQ也会将其与绑定使用的路由键进行匹配,如果匹配成功则消息会投入到消息对列。反之则消息将进入“黑洞”,被丢弃。

42427656_1.png

2.Fanout路由原理


fanout路由.png

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;    }

用生产者发送消息

@Componentpublic 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: 55helloreceive msg a: 55helloreceive msg b: 56helloreceive msg a: 56helloreceive msg b: 57helloreceive msg a: 57helloreceive msg b: 58helloreceive msg a: 58hello

也验证了以上结论。

0 0