RabbitMQ 消息模型:Broker、交换器、队列与收发路径
RabbitMQ 是遵从 AMQP 0-9-1 的消息中间件(Erlang 实现),消息先进入 Exchange(交换器) ,再按类型与绑定规则路由到 Queue(队列) 。本文归纳核心对象、四种交换器、生产/消费典型步骤、Connection 与 Channel 的分工,以及客户端入口。帧级命令名与握手顺序以 AMQP 0-9-1 规范及 RabbitMQ 官方文档为准。
目录
- [RabbitMQ 与 AMQP 的定位](#RabbitMQ 与 AMQP 的定位)
- 核心对象一览
- 交换器类型与路由行为
- [topic 绑定键通配符](#topic 绑定键通配符)
- 路由示意(Mermaid)
- 生产者:从连接到入队
- 消费者:订阅、投递与确认
- [Connection 与 Channel](#Connection 与 Channel)
- 多消费者与轮询
- 客户端入口(多语言)
- 免责声明
RabbitMQ 与 AMQP 的定位
- AMQP (Advanced Message Queuing Protocol):面向消息中间件的开放应用层协议 ,客户端与 Broker 可跨语言、跨厂商交互(具体特性以 0-9-1 规范与实现为准)。
- RabbitMQ :实现 AMQP 的 Broker 之一;另可通过插件支持 STOMP、MQTT 等,但核心路由心智仍建议从 AMQP 模型理解。
| 常见特点 | 说明 |
|---|---|
| 可靠性 | 持久化、publisher confirm 、消费者 ACK 等组合使用 |
| 灵活路由 | Exchange + Binding;内置类型不足时可插件扩展 |
| 扩展与高可用 | 集群、经典镜像队列或 Quorum Queue 等(随版本演进,以文档为准) |
| 可观测性 | 管理插件、指标与日志 |
核心对象一览
| 对象 | 角色 |
|---|---|
| Producer | 发消息;负载常含 payload 与路由相关标签 (如 exchange、routing key )。入队后消费者通常主要处理 payload。 |
| Exchange | 路由中枢;生产者不直接发队列(概念上),而是发到 Exchange。 |
| Queue | 存储消息;与 Exchange 通过 Binding 关联。 |
| Binding | 声明 Exchange 与 Queue 的关系,含 binding key(及参数)。 |
| Consumer | 订阅 Queue,接收投递;确认后 Broker 可删除消息(依 ACK 模式)。 |
| Broker | 服务实例;口语上常叫「一台 RabbitMQ」。 |
Routing key :生产者发布时携带;是否与 binding key 匹配、如何匹配,取决于 Exchange 类型。
交换器类型与路由行为
| 类型 | 行为概要 |
|---|---|
| fanout | 忽略 routing key ;消息复制到所有绑定队列。 |
| direct | routing key 与 binding key 完全相同的队列接收消息。 |
| topic | 点分词 + 通配符匹配(见下节)。 |
| headers | 按消息 headers 匹配,不依赖 routing key;复杂度和性能需自行评估,生产相对较少用。 |
默认交换器("") :AMQP 规定存在名称为空 的 direct 交换器;用默认交换器发队列时,routing key 常被当作队列名路由到对应队列(便于入门,复杂路由仍建议显式 Exchange)。
topic 绑定键通配符
Routing key / binding key 一般为 . 分隔的单词,如 orders.created.cn。
| 符号 | 含义 |
|---|---|
* |
匹配恰好一个单词 |
# |
匹配 零个或多个单词(多段) |
示例(教学用):
| Binding key | 能匹配的 routing key 示例 |
|---|---|
*.orange.* |
a.orange.b |
lazy.# |
lazy、lazy.pink、lazy.pink.rabbit |
路由示意(Mermaid)
publish + routing key
binding
binding
Producer
Exchange
Queue 1
Queue 2
Consumer
Consumer
fanout 示意(同一条消息进多队列):
Producer
fanout X
Q1
Q2
生产者:从连接到入队
典型顺序(教学归纳):
- 与 Broker 建立 TCP Connection ,创建 Channel。
- 声明 Exchange(类型、持久化等)。
- 声明 Queue(持久化、排他、自动删除等)。
- QueueBind :指定 binding key(及参数)。
- Basic.Publish :指定 exchange、routing key、payload。
- Exchange 按规则将消息放入 0...n 个队列。
- 无匹配队列时,行为依赖 mandatory、备份交换器 等配置(可能回退或丢弃)。
- 关闭 Channel / Connection。
text
Producer ──► Channel ──► Exchange ──► Queue(0..n)
│
└── 声明、绑定、发布均在 Channel 上
消费者:订阅、投递与确认
- Connection + Channel。
- 可选 Basic.Qos (prefetch ),限制未 ACK 的在途消息数,利于公平分发 与背压(与 Broker 内部流控配合)。
- Basic.Consume (推模式)或 Basic.Get(拉模式,少用)。
- 收到 Basic.Deliver 后处理业务。
- Basic.Ack (或 Nack/Reject,依场景与重试策略)。
- 关闭资源。
Connection 与 Channel
| 概念 | 说明 |
|---|---|
| Connection | 到 Broker 的 TCP 连接,认证在其上完成。 |
| Channel | Connection 上的轻量虚拟连接 ,有独立 ID;绝大多数 AMQP 命令在 Channel 上发送,避免每条命令都新建 TCP。 |
实践 :多线程应用常为每个线程(或有限个)使用独立 Channel ,不要在多线程间共享同一个 Channel(客户端库通常非线程安全)。
多消费者与轮询
同一队列上挂多个消费者时,Broker 常按 Round-Robin 在消费者间分配消息,实现水平扩展 。若各消息处理耗时差异大,仅靠轮询可能导致慢消费者拖整体 ;可配合 prefetch=1、拆分队列等策略优化。
广播需求 :队列层不提供「一条消息同时被多个消费者各收一份」的默认语义;可用 fanout + 多队列 或 MQTT 等协议语义实现。
客户端入口(多语言)
| 语言 | 常见客户端包名(示例) |
|---|---|
| Java | com.rabbitmq.client(ConnectionFactory、Connection、Channel) |
| Python | pika 或 aio-pika |
| .NET | RabbitMQ.Client |
| Go | amqp091 等 |
协议操作集中在 Channel ;Connection 负责建 Channel 与生命周期。
免责声明
Quorum Queue、流控、集群行为 随版本变化大,部署与调优请以当前 RabbitMQ 官方文档为准。
主题:RabbitMQ、AMQP、Exchange、Queue、路由、Channel。