繼 Direct Exchange(精確匹配)後,Topic Exchange 引入通配符機制,成為生產環境最常用的交換機類型。本文詳細解析通配符規則、綁定鍵設計、Java 客戶端代碼實現,並對比 Direct/Fanout/Topic 三大模式適用場景。
. 分隔的單詞序列,如 audit.irs.corporate。# (井號):**匹配零個或多個單詞**。audit.# 匹配 audit、audit.irs、audit.irs.corporate。* (星號):**匹配恰好一個單詞**。audit.* 只匹配 audit.irs,不匹配 audit 或 audit.irs.corporate。

// 聲明 Topic 交換機
channel.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC, true);
// 發送不同路由鍵消息
String[] routingKeys = {"quick.orange.rabbit", "lazy.orange.elephant", "quick.orange.fox"};
for (String key : routingKeys) {
String msg = "Message with routing key: " + key;
channel.basicPublish("topic_logs", key, null, msg.getBytes(StandardCharsets.UTF_8));
System.out.println("Sent: " + key);
}
*.orange.* (中間詞為 orange)String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "topic_logs", "*.orange.*");
DeliverCallback callback = (consumerTag, delivery) -> {
String msg = new String(delivery.getBody(), StandardCharsets.UTF_8);
System.out.println("Consumer1 received [" + delivery.getEnvelope().getRoutingKey() + "] " + msg);
};
channel.basicConsume(queueName, true, callback, consumerTag -> {});
lazy.# (以 lazy 開頭)String queueName = channel.queueDeclare().getQueue(); channel.queueBind(queueName, "topic_logs", "lazy.#"); // 同樣消費邏輯...
quick.orange.rabbit → 同時進入 Consumer1 (*.orange.*) 和 Consumer2 (不匹配 lazy.#) → **僅 Consumer1 收到**。lazy.orange.elephant → 匹配 *.orange.* 且匹配 lazy.# → **兩個消費者都收到**。quick.orange.fox → 匹配 *.orange.* → **僅 Consumer1 收到**。lazy.pink.rabbit → 匹配 lazy.# → **僅 Consumer2 收到**。| 類型 | 匹配規則 | 適用場景 | 性能 |
|---|---|---|---|
| Direct | RoutingKey 精確等於 BindingKey | 單播、命令分發、固定業務路由 | 最高 (O(1) 哈希查找) |
| Fanout | 無視 RoutingKey,廣播所有綁定隊列 | 廣播通知、日志同步、事件通知 | 高 (無匹配開銷) |
| Topic | 通配符模式匹配 (* / #) | 多維度路由、日志分級收集、微服務事件總線 | 中 (Trie 樹匹配,較 Direct 慢) |
業務域.子系統.操作類型.實體 格式(如 order.payment.success.user),便於通配符訂閱。# 過於寬泛易導致消息洪水,優先使用 * 精確匹配單層。alternate-exchange 導入死信隊列,防止消息靜默丟失。Topic Exchange 以通配符機制實現了多維度、鬆耦合的消息路由,是構建事件驅動架構、微服務異步通信的核心基礎設施。掌握 * 與 # 的語義邊界,設計清晰的路由鍵體系,是用好 RabbitMQ 的關鍵。