首页 / 知识库 / python服务端进阶 / 消息队列入门

05 - RabbitMQ 的架构与工作原理

选定了 RabbitMQ,这一章带你看它内部到底怎么转。重点理解它最有特色的设计——交换机(Exchange),这也是它区别于其他 MQ 的灵魂。

记住一句话:在 RabbitMQ 里,生产者从不直接把消息发给队列,而是发给”交换机”,由交换机决定消息该进哪个(些)队列。


5.1 RabbitMQ 的核心部件

┌──────────┐   发消息    ┌─────────────────────────────────────┐   ┌──────────┐
│ 生产者    │──────────▶│           RabbitMQ Broker            │──▶│ 消费者    │
│ Producer │  (带路由键) │                                     │   │ Consumer │
└──────────┘            │  ┌──────────┐  绑定   ┌──────────┐  │   └──────────┘
                        │  │ 交换机     │───────▶│ 队列 Q1   │  │
                        │  │ Exchange  │───────▶│ 队列 Q2   │  │
                        │  └──────────┘  绑定   └──────────┘  │
                        │       ▲                             │
                        │  按"路由规则"决定进哪个队列            │
                        └─────────────────────────────────────┘
部件作用
Exchange(交换机)消息的”分拣中心”。接收生产者的消息,按规则决定转发到哪些队列。生产者只认识它
Queue(队列)消息真正排队暂存的地方,消费者从这里取消息
Binding(绑定)交换机和队列之间的”连线规则”,告诉交换机”满足什么条件的消息该送到我这个队列”
Routing Key(路由键)生产者给消息贴的”地址标签”,交换机拿它去匹配绑定规则

用邮局来类比整套流程:

你寄信(生产者)
  → 信封上写收件地址(路由键)
  → 交到邮局分拣中心(交换机)
  → 分拣中心按地址规则(绑定)把信投进对应的信箱(队列)
  → 收件人(消费者)从自己的信箱取信

关键点:生产者只把信交给”分拣中心”,它不需要知道有几个信箱、信最终进了哪个。这就是 RabbitMQ 灵活和解耦的来源。


5.2 交换机的四种类型(RabbitMQ 的灵魂)

交换机怎么”分拣”,取决于它的类型。理解这四种类型,就理解了 RabbitMQ 的路由能力。

① Direct(直连)——精确匹配

路由键完全相等才转发。适合”按类型精确派发”。

                              路由键 = "email"
生产者 ──(routing_key=email)──▶ ┌─────────┐ ──绑定 email──▶ [邮件队列]
                              │ Direct  │
                              │ 交换机   │ ──绑定 sms  ──▶ [短信队列]
                              └─────────┘
消息路由键是 email → 只进"邮件队列";是 sms → 只进"短信队列"

② Fanout(扇出)——广播给所有

忽略路由键,把消息复制一份发给所有绑定的队列。这就是 第 02 章 说的”发布/订阅”模型。

                        ┌─────────┐ ──▶ [邮件队列]
生产者 ──(消息)──────────▶│ Fanout  │ ──▶ [短信队列]
                        │ 交换机   │ ──▶ [推荐队列]
                        └─────────┘ ──▶ [统计队列]
一条"用户已注册" → 所有队列人手一份(一次广播,多方响应)

③ Topic(主题)——按模式通配匹配

路由键按 . 分段,用 *(匹配一段)和 #(匹配多段)做模糊匹配。最灵活,适合复杂的分类订阅。

生产者发 routing_key = "order.cn.vip"
                        ┌─────────┐
                        │ Topic   │ ──绑定 order.#     ──▶ [所有订单队列]   ✅命中
                        │ 交换机   │ ──绑定 *.cn.*      ──▶ [中国区队列]     ✅命中
                        └─────────┘ ──绑定 user.#      ──▶ [用户事件队列]   ✗不命中

一条消息可同时命中多个规则,进多个队列

④ Headers(头匹配)——按消息属性匹配

按消息的自定义属性(headers)而非路由键匹配。用得较少,知道有这么个东西即可。

小结:四种类型怎么记

类型匹配方式一句话场景
Direct路由键精确相等按明确类型派发(这条给邮件、那条给短信)
Fanout无视路由键,全广播一个事件通知所有人(发布/订阅)
Topic路由键通配匹配灵活的按主题订阅(最常用、最强大)
Headers按消息头属性特殊需求,少用

实际项目里,Direct 和 Topic 用得最多,Fanout 用于广播。搞懂前三个就够应付绝大部分场景了。


5.3 一条消息在 RabbitMQ 里的完整旅程

把前面的部件串起来,走一遍完整流程:

① 生产者(FastAPI) 连接 Broker,发送消息
   消息内容: {"user_id": 1001}   路由键: "user.registered"


② 消息到达【交换机】(比如一个 Topic 交换机)


③ 交换机根据【绑定规则】匹配路由键,决定投给哪些【队列】
   匹配到: 邮件队列(绑定 user.#)、统计队列(绑定 user.registered)

        ├──────────────┬──────────────┐
        ▼              ▼
   [邮件队列]       [统计队列]     (消息各进一份,在队列里排队)
        │              │
        ▼              ▼
④ 各自的【消费者】从队列取出消息处理
   邮件worker发欢迎邮件      统计worker更新数据
        │              │
        ▼              ▼
⑤ 处理成功后发【确认 ACK】,Broker 才把消息从队列删除

5.4 补充两个概念:Connection 与 Channel

实际连接 RabbitMQ 时会遇到这两个词,简单理解即可:

┌────────────────────────────────────────┐
│         一个 Connection(TCP 连接)        │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐    │
│  │Channel 1│ │Channel 2│ │Channel 3│    │
│  └─────────┘ └─────────┘ └─────────┘    │
└────────────────────────────────────────┘
        应用 ←──── 网络 ────→ RabbitMQ Broker
  • Connection:应用和 Broker 之间的一条 TCP 网络连接,建立成本较高。
  • Channel(信道):在一条 Connection 上开的逻辑通道,真正的收发消息都在 Channel 上进行。

为什么要 Channel?因为建 TCP 连接很贵。一个应用建一条 Connection,然后在上面开多个轻量的 Channel 复用,既省资源又能并发。你只要记住:一条连接可以开很多信道,实际干活的是信道。


5.5 部署形态:Broker 是独立服务

再强调一次架构上的关键认知:RabbitMQ Broker 是一个独立运行的服务,通常用 Docker 单独跑一个容器。你的 FastAPI 和消费者都通过网络(默认端口 5672)连它。它还自带一个 Web 管理后台(默认端口 15672),能可视化地看队列、消息堆积情况。

┌──────────────┐        ┌────────────────────┐        ┌──────────────┐
│ FastAPI 容器  │─5672──▶│  RabbitMQ 容器       │◀─5672──│ 消费者 容器    │
│ (生产者)      │        │  管理后台 :15672     │        │ (worker)     │
└──────────────┘        └────────────────────┘        └──────────────┘
              三个独立服务,通过网络协作(正好用你学过的 Docker 编排)

本章小结

知识点要点
核心设计生产者发给交换机,交换机按规则路由到队列,不直连队列
四大部件Exchange(分拣中心)、Queue(排队处)、Binding(连线规则)、Routing Key(地址标签)
交换机类型Direct(精确)、Fanout(广播)、Topic(通配,最常用)、Headers(少用)
Connection/Channel一条 TCP 连接上开多个轻量信道复用,实际收发在信道上
部署Broker 是独立服务(端口 5672),自带 Web 管理后台(15672),适合用 Docker 跑

下一章预告:把 RabbitMQ 接到你的 FastAPI 项目里——从架构视角看生产者、消费者、Broker 怎么分工部署,消息怎么流动。


上一章 ← 04 - 选型 | 下一章 → 06 - FastAPI + RabbitMQ 的整合架构思路