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

0.回顾


Spring Boot RabbitMQ 入门(二) 环境搭建
上篇文章我们学习了以下几点:

  • 1.如何创建交换器
  • 2.如何创建对列
  • 3.如何将队列绑定到交换器
  • 4.如何创建消费者

1.Exchange功能介绍


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

Spring Boot RabbitMQ 入门(三)之 Fanout交换器_第1张图片
42427656_1.png

2.Fanout路由原理


Spring Boot RabbitMQ 入门(三)之 Fanout交换器_第2张图片
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;
    }

用生产者发送消息

@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

也验证了以上结论。

你可能感兴趣的:(Spring Boot RabbitMQ 入门(三)之 Fanout交换器)