--- tags: [mq/rabbitmq, exchange-routing, direct-exchange, fanout-exchange, topic-exchange, headers-exchange, delay-exchange] create time: 2026-08-08 18:50 update time: 2026-08-08 18:50 --- # Exchange 路由机制 ## 概述 Exchange(交换机)是 RabbitMQ 消息路由的核心组件,充当生产者与队列之间的中间层。生产者在发送消息时指定 Exchange 名称和 routing key,RabbitMQ 根据 Exchange 类型和路由规则将消息分发到一个或多个 Queue。掌握四种内置 Exchange 类型以及插件扩展的延迟交换能力,是设计可靠消息系统的基础。 ## 核心原理 ### 四种内置 Exchange 类型 #### Direct Exchange — 精确匹配 Direct Exchange 使用完全匹配原则:routing key 必须与 Queue 绑定到 Exchange 时的 binding key 完全一致,消息才会被投递。 ```mermaid sequenceDiagram participant P as 生产者 participant E["Direct Exchange"] participant Q1["Queue A (key: order.create)"] participant Q2["Queue B (key: order.* )"] participant Q3["Queue C (key: *.pay)"] P->>E: 发送消息
routing key: "order.create" E->>Q1: 匹配成功,投递 Note over E,Q1: "order.create" == "order.create" E->>Q2: 匹配失败 Note over E,Q2: "order.create" ne "order.*" E->>Q3: 匹配失败 Note over E,Q3: "order.create" ne "*.pay" ``` 关键特征:一对一或一对多投递(多个 Queue 绑定了相同的 binding key)。这是最常用也最可预测的路由方式。 #### Fanout Exchange — 广播模式 Fanout Exchange 忽略 routing key,将消息投递到所有绑定到该 Exchange 的 Queue。每次收到消息就是群发。 ```mermaid sequenceDiagram participant P as 生产者 participant E["Fanout Exchange"] participant Q1["订单队列"] participant Q2["日志队列"] participant Q3["通知队列"] P->>E: 发送消息
routing key: (任意值) E->>Q1: 广播投递 E->>Q2: 广播投递 E->>Q3: 广播投递 Note right of E: 忽略 routing key
全部投递 ``` 典型场景:事件广播、配置刷新、缓存失效通知。不需要关心消息内容被哪些消费者处理。 #### Topic Exchange — 通配符匹配 Topic Exchange 是最灵活的路由模式,支持通配符匹配: - `*`(星号)匹配**恰好一个词** - `#`(井号)匹配**零个或多个词** 词之间以点号 `.` 分隔。匹配规则示例: | routing key | binding key | 是否匹配 | |-------------|------------|---------| | `quick.orange.fox` | `*.orange.*` | 是 | | `quick.orange.fox` | `quick.*.fox` | 是 | | `quick.brown.fox` | `*.orange.*` | 否 | | `quick.orange.male.rabbit` | `#` | 是(匹配所有) | | `lazy.orange.cat` | `lazy.#` | 是 | ```mermaid sequenceDiagram participant P as 生产者 participant E["Topic Exchange"] participant Q1["Queue: *.create"] participant Q2["Queue: *.pay.*"] participant Q3["Queue: #"] P->>E: routing key: "order.create" E->>Q1: 匹配 "*" -> 投递 E->>Q2: "order.pay.*" ne "*.pay.*" -> 不投递 E->>Q3: "#" -> 投递 P->>E: routing key: "order.pay.success" E->>Q1: "*.create" ne "order.pay.success" -> 不投递 E->>Q2: 匹配 "*.pay.*" -> 投递 E->>Q3: "#" -> 投递 ``` #### Headers Exchange — 基于属性匹配 Headers Exchange 忽略 routing key,通过检查消息的 headers 属性(key-value 对)来决定路由。可以设置 `match` 参数:`all`(所有 header 都匹配)或 `any`(任一 header 匹配即可)。 > [!WARNING] > Headers Exchange 性能较差且灵活性不如 Topic Exchange,官方文档明确标注"不推荐在生产中使用"。应优先选择 Topic Exchange。 ### 死信交换机的特殊绑定 Dead Letter Exchange(DLX)本质上也是一个普通 Exchange,只是通过队列属性间接触发。当队列中的消息满足以下条件之一时,会被重新路由到 DLX: - 消息被 nack 且不重新入队(`requeue=false`) - 消息 TTL 过期 - 队列长度限制已满 ```yaml # 队列声明时指定 DLX queue: name: "order.processing" arguments: x-dead-letter-exchange: "dead-letter-exchange" x-dead-letter-routing-key: "order.dead" ``` ### 延迟交换插件(x-delayed-message) RabbitMQ 本身不提供延迟消息功能,需要安装 `rabbitmq_delayed_message_exchange` 插件后使用自定义 Exchange 类型 `x-delayed-message`。它通过消息的 `x-delay` header 控制投递时机。 ```go // Go 代码示例:声明延迟 Exchange // (amqp.go 库简化写法) args := amqp.Table{ "x-delayed-type": "direct", // 内部转发使用的 Exchange 类型 } ch.ExchangeDeclare( "delayed.exchange", // name "x-delayed-message", // type true, // durable false, // auto-deleted false, // internal false, // no-wait nil, // args args, // 自定义参数 ) ``` 构建消息时设置 `x-delay` header(单位毫秒): ```go // Go 代码示例:带延迟头的消息 msg := amqp.Publishing{ Body: []byte(`{"orderId":"123"}`), Headers: amqp.Table{ "x-delay": uint32(60000), // 延迟 60 秒 }, } ``` > [!TIP] > 面试常考点:RabbitMQ 原生不支持延迟消息。常见替代方案有定时任务轮询、Redis ZSet 定时弹出、或使用 Kafka 的分区时间排序特性。但在高可靠性场景中,x-delayed-message 插件是最直接可靠的方案。 ## 实践场景 | 场景 | 推荐 Exchange | 原因 | |------|--------------|-----| | 订单创建通知下游 | Direct | 精确控制消息去向 | | 全局缓存失效广播 | Fanout | 所有服务实例都需要收到 | | 日志分级收集(info/error/warn) | Topic | 按级别前缀灵活路由 | | 支付回调不同金额段分流 | Topic | 按 `amount.linux``amount.high` 等维度拆分 | | 超时未支付取消订单 | x-delayed-message | 精确控制延迟投递时间 | | 死信消息归档 | Direct + DLX 属性 | 标准化异常流程处理 | > [!TIP] > 秋招面试技巧:当被问到"如何设计一个支持多种消息类型的路由系统"时,优先考虑 Topic Exchange 的通配符能力,而非为每种类型创建独立的 Direct Exchange。Topic Exchange 天然支持层级化路由,运维上更简洁。 ## 关联笔记 - [[消息持久化与可靠性投递]] - [[ACK 确认与死信队列]] - [[推拉结合消费模式]]