🎯 什麼情境該想到我

當你「要讓發送者把訊息送到接收者,但兩者不該彼此直接知道對方」的時候:中間需要一條講好的邏輯管道。

⚙️ 怎麼用(步驟 / 公式)

意圖:用訊息系統中的邏輯通道連接發送者與接收者;發送者把訊息寫入通道,接收者從通道讀取。

做法 / 結構要點:

  • 通道是有名字、有位址的邏輯路徑,決定訊息往哪裡流。
  • 發送者只需知道要寫入哪個通道,不需知道誰在接收(反之亦然)。
  • 通道的種類(點對點 / 發布訂閱等)決定訊息被一個或多個接收者取用。

★ 「通道」在各家 broker 裡叫什麼

點對點通道發布訂閱通道
Kafka★ topic + 同一個 consumer grouptopic + 多個 consumer group
RabbitMQqueue(多個 consumer 競爭)fanout/topic exchange → 每個 consumer 一個 queue
SQS/SNSSQS queueSNS topic → 多個 SQS queue
NATS JetStreamstream + queue groupstream + 多個 durable consumer

★★ Kafka 的關鍵差異:通道的「種類」不是建立時決定的,而是由消費者怎麼分組決定的。
同一個 topic,一個 consumer group 讀 = 點對點;三個 group 各自讀 = 發布訂閱。
這和 EIP 書裡「queue vs topic 是兩種東西」的模型不同——寫 2003 年的 JMS 時沒有這個選項。

★★ 通道命名與治理:這是唯一真正會痛的長期問題

# ★ 一套可行的命名規範(領域.實體.事件.版本)
orders.order.placed.v1
billing.invoice.issued.v1
inventory.stock.reserved.v1

# ★ 為什麼要帶版本:schema 不相容變更時,你需要能「同時跑兩條通道」
orders.order.placed.v1   ← 舊消費者
orders.order.placed.v2   ← 新消費者

要在規範裡定死的五件事:

  1. ★ 命名格式(誰擁有這個通道,一看就知道)
  2. ★ 這是命令還是事件通道(語義不可混用,見 命令訊息/事件訊息)
  3. ★ schema 放在哪(schema registry、.proto repo)
  4. ★ retention 多久(Kafka 的 retention.ms、SQS 的 retention、RabbitMQ 的 TTL)
  5. 誰可以寫入(★ 寫入權就是所有權)

★ 一個通道應該只承載一種訊息型別——這就是 資料型別通道。
混著放,消費者每則都要先判斷型別,等於自己實作一個路由器。

★ 通道數量的實務上限(不是無限的)

Kafka:★ 分區總數是有成本的(每個分區 = 檔案句柄 + 記憶體 + controller metadata)
       單叢集數千到數萬分區是常見上限;★ 「每個使用者一個 topic」一定會爆
RabbitMQ:★ 每個 queue 是一個 Erlang process。數萬 queue 可行,但長佇列會拖慢整體
SQS:★ 帳號級配額限制;動態建立大量 queue 要先確認配額

★ 反模式:用「每個實體一個通道」來做隔離。
要隔離就用分區鍵(同一個實體的訊息進同一個分區),不要用通道數量。

★ Go 的通道 ≠ EIP 的通道

ch := make(chan Order, 100)    // ★ Go 的 channel:行程內、無持久化、行程死了就沒了

兩者名字一樣但完全不同層次。Go channel 沒有持久化、沒有重送、沒有 DLQ。
⚠️ 常見錯誤:用 buffered channel 當「佇列」來削峰 → 行程重啟就丟光。
(Go channel 的正確用法見 工具-靠通訊共享記憶體。)

🧪 我實際套用的紀錄

  • (待填)

⚠️ 注意 / 什麼時候不適用

  • 通道是設計時決定的固定路徑,不是動態內容路由;要依內容分流請用路由器。

  • 通道數量過多會增加管理負擔,需要命名與治理規範。

  • ★ Kafka 裡「點對點 vs 發布訂閱」是由消費者分組決定的,不是通道型別。這和 EIP 的 JMS 模型不同。

  • ★★ 通道命名與治理是唯一會長期痛的問題。命名要看得出擁有者,並帶版本。

  • ★ 一個通道只放一種訊息型別(資料型別通道)。混放等於強迫每個消費者自己路由。

  • ★ 不要用「每個實體一個通道」做隔離。分區數/queue 數都有實際上限,要隔離就用分區鍵。

  • ★ retention 是設計決定,不是預設值。Kafka 過期就真的沒了;SQS 最長 14 天。

  • ★ Go 的 chan 不是訊息通道:行程內、無持久化。用它削峰,重啟就丟光。

  • 通道是設計時的固定路徑,依內容分流要用 訊息路由器。

🔗 相關工具