【Spring AMQP 三大交换机】

Spring AMQP 三大交换机详解:Fanout、Direct、Topic(附完整示例 + 使用场景)

在使用 Spring Boot + RabbitMQ 做消息队列开发时,经常会遇到三种交换机类型:

  • FanoutExchange
  • DirectExchange
  • TopicExchange

很多刚接触 MQ 的同学都会有几个疑问:

  • 这三种交换机到底有什么区别?
  • routingKey 是干什么的?
  • 实际项目应该选哪一种?

这篇文章会用 通俗解释 + 简单代码 + 实际场景,把三种交换机彻底讲清楚。

为了让重点更清晰,本文 只写核心代码,不写配置文件


一、RabbitMQ 的核心结构

很多人刚开始会以为消息队列是这样:

复制代码
生产者 → 队列 → 消费者

其实 RabbitMQ 并不是这样工作的

真正的结构是:

复制代码
Producer → Exchange → Queue → Consumer

也就是说:

生产者永远只把消息发送到 Exchange(交换机)。

然后 Exchange 再根据规则,把消息分发到不同队列。

不同类型的 Exchange,决定了:

消息会被分发到哪些队列。


二、FanoutExchange(广播模式)

1、工作原理

FanoutExchange 是最简单的一种交换机。

它的规则只有一句话:

不看 routingKey,直接把消息广播到所有绑定的队列。

结构如下:

复制代码
           FanoutExchange
             /   |   \
           Q1   Q2   Q3

只要有消息进入交换机:

复制代码
Producer → Exchange → 所有队列都会收到

2、声明持久化队列和交换机

java 复制代码
@Bean
public Queue queue1(){
    return new Queue("queue1", true);
}

@Bean
public Queue queue2(){
    return new Queue("queue2", true);
}

@Bean
public FanoutExchange fanoutExchange(){
    return new FanoutExchange("fanout.exchange");
}

@Bean
public Binding binding1(){
    return BindingBuilder.bind(queue1()).to(fanoutExchange());
}

@Bean
public Binding binding2(){
    return BindingBuilder.bind(queue2()).to(fanoutExchange());
}

这里的 true 表示 持久化队列,RabbitMQ 重启后不会丢失。


3、发送消息

java 复制代码
@Autowired
private RabbitTemplate rabbitTemplate;

public void send(){

    rabbitTemplate.convertAndSend(
            "fanout.exchange",
            "",
            "系统广播消息"
    );
}

注意:

复制代码
FanoutExchange 不需要 routingKey

所以直接写空字符串。


4、消费者

java 复制代码
@RabbitListener(queues = "queue1")
public void receive1(String msg){
    System.out.println("queue1收到:" + msg);
}

@RabbitListener(queues = "queue2")
public void receive2(String msg){
    System.out.println("queue2收到:" + msg);
}

5、适用场景

Fanout 非常适合:

  • 系统广播
  • 缓存同步
  • 日志收集
  • 事件通知

例如:

复制代码
用户注册成功

需要:

  • 发优惠券
  • 发短信
  • 写日志

就可以:

复制代码
user-service → fanoutExchange

多个服务同时消费。


6、优缺点

优点:

  • 结构简单
  • 扩展容易

缺点:

  • 所有队列都会收到消息
  • 可能产生无用消息

三、DirectExchange(精准路由)

1、工作原理

DirectExchange 根据 routingKey 精确匹配

结构:

复制代码
           DirectExchange
           /            \
      order.queue     log.queue
        (order)         (log)

规则:

复制代码
routingKey = order → order.queue
routingKey = log   → log.queue

2、声明交换机

java 复制代码
@Bean
public DirectExchange directExchange(){
    return new DirectExchange("direct.exchange");
}

3、绑定 routingKey

java 复制代码
@Bean
public Binding orderBinding(){

    return BindingBuilder
            .bind(new Queue("order.queue",true))
            .to(directExchange())
            .with("order");
}

4、发送消息

java 复制代码
rabbitTemplate.convertAndSend(
        "direct.exchange",
        "order",
        "订单创建成功"
);

只有绑定了 order 的队列才会收到消息。


5、适用场景

DirectExchange 常用于:

  • 订单系统
  • 日志系统
  • 业务分类处理

例如:

复制代码
order.create
order.pay
order.cancel

不同服务处理不同消息。


6、优缺点

优点:

  • 路由精准
  • 性能高

缺点:

  • routingKey 必须完全匹配

四、TopicExchange(通配符路由)

1、工作原理

TopicExchange 是 最灵活的交换机

它支持 通配符匹配

两个常见符号:

复制代码
*  匹配一个单词
#  匹配多个单词

例如:

复制代码
order.create
order.pay
order.cancel

结构:

复制代码
            TopicExchange
            /            \
        order.#       order.create

规则:

复制代码
order.# → 所有订单消息
order.create → 只接收创建订单

2、声明交换机

java 复制代码
@Bean
public TopicExchange topicExchange(){
    return new TopicExchange("topic.exchange");
}

3、绑定规则

java 复制代码
@Bean
public Binding topicBinding(){

    return BindingBuilder
            .bind(new Queue("order.queue",true))
            .to(topicExchange())
            .with("order.#");
}

4、发送消息

java 复制代码
rabbitTemplate.convertAndSend(
        "topic.exchange",
        "order.create",
        "创建订单"
);

5、适用场景

TopicExchange 常见于:

  • 微服务架构
  • 事件驱动系统
  • 大型业务系统

例如:

复制代码
user.login
user.logout
user.register

不同模块订阅不同事件。


6、优缺点

优点:

  • 非常灵活
  • 支持复杂路由

缺点:

  • routingKey 设计必须规范

五、三种交换机对比

类型 routingKey 特点 场景
Fanout 不需要 广播 系统通知
Direct 精确匹配 精准路由 订单系统
Topic 通配符 灵活 微服务

简单记忆:

复制代码
Fanout  = 广播
Direct  = 精确路由
Topic   = 模糊路由

六、真实项目案例

假设有一个 用户注册系统

用户注册成功后,需要做三件事:

复制代码
发优惠券
发短信
写日志

可以这样设计:

复制代码
       UserService
             ↓
      FanoutExchange
     /       |      \
优惠券服务 短信服务 日志服务

这样一条消息就可以同时通知多个系统。


七、面试常见问题

1 RabbitMQ 为什么需要 Exchange?

因为 Exchange 可以 解耦生产者和队列

生产者只需要发送消息,不需要关心具体队列。


2 Fanout 和 Direct 的区别

Fanout:

复制代码
广播

Direct:

复制代码
精准路由

3 为什么 Topic 使用最多?

因为 Topic 既可以实现:

  • Direct 的精准路由
  • Fanout 的广播

所以 灵活性最高


八、总结

三种交换机可以这样理解:

  • Fanout:一条消息,所有人都听见
  • Direct:一条消息,只给指定的人
  • Topic:一条消息,按规则筛选接收人

掌握这三种交换机之后,你就已经理解了 RabbitMQ 消息路由的核心机制

如果这篇文章对你有帮助,欢迎点赞收藏 ⭐

后面我还会继续写:

  • Spring AMQP 实战
  • RabbitMQ 延迟队列
  • RabbitMQ 死信队列
相关推荐
重庆小透明2 小时前
微服务,不仅仅是“小服务”
java·后端·spring cloud·微服务·云原生·架构
孟沐2 小时前
JDBC 入门大白话文档
后端
李长渊哦2 小时前
OpenClaw 本地部署完全指南:从环境验证到启动运行
后端·arcgis
Java编程爱好者2 小时前
Spring Boot 中关于 Bean 加载、实例化、初始化全生命周期的扩展点
后端
七牛云行业应用2 小时前
别瞎折腾了!4 步排查法,手把手教你搞定 OpenClaw Skills 各种安装报错
后端·openai·agent
Java编程爱好者2 小时前
DBA 经验:MySQL性能最重要的参数只有2个!
后端
武子康2 小时前
大数据-245 离线数仓 - 电商分析 Hive 拉链表入门实战:缓慢变化维 SCD 类型、建表加载与常见错误速查
大数据·后端·apache hive
huahailing10242 小时前
Spring Boot 异步事务最佳实践:TransactionTemplate 实战指南
数据库·spring boot·后端
二月夜2 小时前
记SpringBoot升级Tomcat引发的两类典型问题及解决方案
spring boot·后端·tomcat