Fanout Exchange_RabbitMQ

在订阅模型中,多了一个exchange角色,而且过程略有变化:

  • Publisher:生产者,也就是要发送消息的程序,但是不再发送到消息队列中,而是发送给交换机
  • Exchange:交换机,接收生产者发送的消息,知道如何处理消息,如:递交给某个队列、递交给所有队列、或是将消息丢弃。如何操作,取决于Exchange的类型。
  • Exchange有以下3种类型:
  • Fanout:广播,将消息发送给所有绑定到交换机的队列。
  • Direct:定向,将消息发送给符合指定 routing key 的队列。
  • Topic:通配符,将消息发送给符合 routing pattern(路由模式)的队列。
  • Consumer:消费者,与以前一样,订阅队列。
  • Queue:接收消息、缓存消息。


Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此 如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息就会丢失。

Fanout(广播模式)

Fanout Exchange 会将接收到的消息广播到每一个跟其绑定的queue

Fanout Exchange_RabbitMQ_02

Fanout消息发送流程

  1. 可以有多个队列
  2. 每个队列都要绑定到Exchange
  3. 生产者发送的消息,只能发送给交换机,交换机来决定要发给哪个队列。
  4. 交换机把消息发送给绑定的所有队列。
  5. 订阅队列的消费者都能拿到消息。

声明交换机与队列

  • 创建一个Fanout类型的交换机,名称为 my.fanout
  • 创建两个队列:fanout.A、fanout.B
  • 将队列绑定到交换机
@Configuration
public class FanoutRabbitConfig {

    /**
     * 创建交换机
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        //创建名为fanoutExchange的交换机
        return new FanoutExchange("my.fanout");
    }

    /**
     * 创建队列fanout.A
     */
    @Bean
    public Queue AMessage() {
        return new Queue("fanout.A");
    }

    /**
     * 创建队列fanout.B
     */
    @Bean
    public Queue BMessage() {
        return new Queue("fanout.B");
    }

    /**
     * 绑定队列 fanout.A 到交换机
     */
    @Bean
    public Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(AMessage).to(fanoutExchange);
    }

    /**
     * 绑定队列 fanout.B 到交换机
     */
    @Bean
    public Binding bindingExchangeB(Queue BMessage, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(BMessage).to(fanoutExchange);
    }
}

消息发送

通过rabbitTemplate.convertAndSend()方法将消息发送给交换机


@Component
public class FanoutSender {

    @Resource
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String context = "hello, everyone";
        System.out.println("生产者发送消息: " + context);
        this.rabbitTemplate.convertAndSend("my.fanout", "", context);
    }
}

消息接收

使用@RabbitListener注解分别监听两个队列

@Component
public class FanoutListener {

    //分别监听三个队列
    @RabbitListener(queues = "fanout.A")
    public void listenQueueA(String msg) {
        System.out.println("消费者A接收到: " + msg);
    }

    @RabbitListener(queues = "fanout.B")
    public void listenQueueB(String msg) {
        System.out.println("消费者B接收到: " + msg);
    }
}

测试结果

Fanout Exchange_RabbitMQ_03