RabbitMQ 核心模型:一条消息如何完成路由与消费(二)
系列导航:
- 上一篇:RabbitMQ 入门:为什么系统需要消息队列(一)
- 当前篇:RabbitMQ 核心模型:一条消息如何完成路由与消费(二)(本文)
- 下一篇:RabbitMQ 路由设计:Exchange 与 Queue 怎么选(三)
上一篇回答了“为什么需要消息队列”,这一篇只解决第二个问题:一条消息进入 RabbitMQ 之后,最小流转路径到底是什么。你不需要先背完所有术语,只要抓住最核心的心智模型:消息由谁发出、经过谁路由、落到哪里、最后被谁消费。
本文刻意不展开详细的路由类型对比,也不进入 ack、prefetch、顺序、背压这些后续主题。先把一条消息的骨架路径看清,再去理解后面的控制与可靠性机制会更容易。
从 order.created 这个共享示例开始
三篇 overview 文章都使用同一个事件:
{
"eventId": "01J...",
"eventType": "order.created",
"occurredAt": "2026-07-15T10:00:00Z",
"orderId": "ORD-20260715-001",
"customerId": "C10086"
}
假设订单服务完成下单后,要把这个事件交给库存和通知两个后续业务。先沿着六个核心角色理解职责,随后再用一张完整路径图把它们串起来。
接下来每个角色只需要先记住一个主要职责。
先记住这六个角色
一条消息依次经过谁
沿着 order.created 的流转顺序,先记住每个角色最核心的一项职责。
- 发布
- 路由
- 消费
- 01Producer订单服务产生业务事实
把“订单已创建”编码成消息,并携带
order.created这样的路由信息。它负责表达发生了什么,不替下游完成具体业务。 - 02ConnectionTCP 长连接建立底层连接
承载客户端与 RabbitMQ 之间的 AMQP 通信。Connection 建立成本较高,通常应当长期复用,而不是每发送一条消息就重新创建。
- 03Channel轻量通道执行发布操作
发布消息、声明拓扑和开始消费等协议操作都在 Channel 中进行。它复用 Connection,不是另一条独立的 TCP 连接。
- 04Exchange路由决策判断消息去向
根据 Exchange 类型、Binding 和 routing key 选择一个或多个目标 Queue。Exchange 负责路由,不负责保存消息。
- 05Queue保存与缓冲保存并等待消费
接住已经路由成功的消息,在消费者处理之前提供缓冲。不同业务通常使用独立 Queue,各自积压、消费和恢复。
- 06Consumer业务处理者接收并处理消息
从具体 Queue 接收消息,再执行库存预留、通知发送等业务逻辑。Consumer 订阅的是 Queue,而不是 Exchange。
到这里,一条消息的核心路径就可以压缩成一句话:
Producer 通过 Connection 上的 Channel 把消息发布到 Exchange,Exchange 把消息路由到一个或多个 Queue,Consumer 再从这些 Queue 中接收并处理消息。
用一条路径把它串起来
把 order.created 代入刚才的模型,可以得到下面这条最小流转:
这条路径里有两个非常重要的边界:
- Exchange 决定消息去哪里
- Queue 决定消息在哪里等着被消费
只要这两个边界不混淆,后面学路由设计、消费控制和可靠性机制都会顺很多。
默认 Exchange 为什么看起来像“直接发 Queue”
很多入门示例会给人一种印象:好像 RabbitMQ 可以直接把消息发到某个 Queue。造成这种感觉的原因,是 RabbitMQ 预先提供了一个特殊的 Exchange,也就是 默认 Exchange。
客户端使用空字符串 "" 发布时,表示把消息发到这个默认 Exchange。RabbitMQ 会自动把每个 Queue 以“队列名作为路由键”的方式隐式绑定到它上面。
于是看起来就像这样:
发布到 ""
Routing Key = inventory.order-events
=> 消息进入同名 Queue
这对点对点入门示例很方便,但本质上仍然是:
- 先发布到 Exchange
- 再由 Exchange 路由到 Queue
也就是说,默认 Exchange 只是把这一步做得很像“直接发 Queue”,并没有改变 RabbitMQ 的基本模型。
什么叫“不可路由消息”
如果消息已经发布到某个 Exchange,但根据当前规则没有任何 Queue 能接住它,这条消息就是不可路由消息。
最常见的场景是:
- 路由键写错了
- 目标 Queue 还没声明
- Exchange 和 Queue 之间根本没有建立匹配关系
例如,订单服务发出的是 order.created,但系统里没有任何规则能让这条消息落到 Queue,那么它就不会凭空出现到消费者那边。
在这里你只需要先建立一个基础认识:发布成功不等于一定有消费者能收到,前提是消息必须先被正确路由。
至于发布方如何感知“没路由到任何 Queue”、系统又该如何做兜底处理,会在后续关于发布可靠性的文章里再展开。
本篇只保留一个够用的心智模型
如果把今天的内容再压缩一次,可以记成三层:
发布层:Producer -> Connection -> Channel
路由层:Exchange -> Queue
消费层:Queue -> Consumer
每当你看到 RabbitMQ 某个新概念时,都可以先问它属于哪一层。只要这条主线还清楚,细节就不容易学散。
下一篇会继续沿用 order.created,但不再讲“消息怎么流”,而是专门回答:业务拓扑应该怎么设计,Exchange 和 Queue 到底怎么选。
本篇解决了什么:
- 用统一的
order.created示例说明了消息从发布到消费的最小流转路径 - 明确了 Producer、Connection、Channel、Exchange、Queue、Consumer 的单一职责
- 解释了默认 Exchange 为什么看起来像“直接发 Queue”,但本质仍然先过 Exchange
- 建立了“发布成功不等于一定被消费,前提是先路由成功”的基础认知