🎯 什麼情境該想到我

當你「路由規則需要能動態更新,而不是寫死在路由器裡」的時候。

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

意圖:讓路由能在不改程式的情況下設定與變更。

做法要點:

  • 路由器維護一張路由規則表(控制表)。
  • 各接收端透過一條特別的「控制通道」向路由器註冊自己「能處理什麼」。
  • 路由器依這張表決定每則訊息的轉送目的地。
  • 等於一個能自我配置的內容路由器。

★ 核心機制:目的地自己來註冊

① 目的地啟動時,往 [[控制匯流排]] 發一則「我要收什麼」
② 路由器維護一份路由表(★ 有狀態)
③ 訊息進來,查表決定去向
④ ★ 目的地下線/逾時沒續約 → 從表裡移除
type Registration struct {
    Destination string        `json:"destination"`   // 通道名
    MatchTypes  []string      `json:"match_types"`   // 想收哪些 type
    TTL         time.Duration `json:"ttl"`           // ★★ 必須有 TTL
}

★★ TTL + 續約(lease)是這個模式的關鍵,也是最常被省略的部分:
沒有 TTL → 目的地非正常關閉(OOM、kill -9)後路由表永遠留著它 →
訊息一直送去一個沒人聽的通道,而且沒有錯誤。
→ ★ 註冊必須是「租約」,要定期續約;路由器要有清理過期項目的迴圈。

★★ 先問:你真的需要它嗎?這是路由家族裡最少用到的一個

★ 動態路由器解決的問題是「目的地清單會在執行期改變,而路由器不該重新部署」
→ 但今天有更好的工具:
  ① ★ 發布訂閱 + 消費者自己決定要不要訂閱 —— 根本不需要路由表
  ② ★ 服務發現/Kubernetes Service —— 基礎設施層已經在做「誰在線」
  ③ ★ broker 的原生訂閱機制(RabbitMQ binding、SNS subscription)
     → ★★ 「目的地自己註冊」在 RabbitMQ 上就是「消費者自己宣告 binding」,
        broker 已經免費提供了整套(含斷線自動移除)

★★ 判準:你需要的是「動態的目的地」還是「動態的規則」?
動態目的地 → 用 發布訂閱通道,讓消費者自己訂閱。這是預設答案。
動態規則(同一個目的地,但條件會變)→ 那是 內容路由器 + 可設定的規則。

★ 自己寫動態路由器真正合理的場景很窄:
需要「路由決策集中可觀測」(合規要求知道每則訊息去了哪),
或 broker 的訂閱機制不足以表達你的規則。

★ 有狀態帶來的三個代價

① ★★ 路由表要持久化或可重建
   路由器重啟 → 表空了 → ★ 所有訊息都變成「無法路由」
   → 要嘛持久化(多一個儲存依賴),要嘛啟動時廣播「請重新註冊」並等待一段時間

② ★ 多個路由器實例要共享路由表
   否則 A 實例知道某個目的地、B 實例不知道 → ★ 同樣的訊息隨機被送到不同地方
   → 需要共享儲存(Redis/etcd),而它又變成新的單點

③ ★ 註冊的權限控制
   任何人都能註冊 → ★ 惡意註冊可以把別人的訊息導給自己(資料洩漏)
   → 註冊要驗證身分;目的地通道要白名單(同 [[回覆位址]] 的問題)

★ 兄弟辨析

差別
內容路由器★ 規則寫死在路由器裡(無狀態)
收件人清單一則訊息送給多個目的地
路由單★ 路徑寫在訊息裡,不需要中央路由表
控制匯流排★ 註冊訊息走的通道
發布訂閱通道★★ 多數「動態目的地」需求的正確答案

🧪 我實際套用的紀錄

  • (待填)

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

  • 需維護規則表與註冊機制的可靠性。

  • 註冊資訊過期或衝突會造成誤路由。

  • 比靜態路由複雜;規則穩定時用內容路由器即可。

  • ★★ 多數「動態目的地」需求該用 發布訂閱通道,讓消費者自己訂閱。自己寫路由表的合理場景很窄。

  • ★★ 註冊必須是有 TTL 的租約。沒有 TTL → 目的地被 kill 後路由表永遠留著它,訊息送去沒人聽的通道且無錯誤。

  • ★ 路由器重啟後路由表是空的 → 所有訊息都無法路由。要持久化,或啟動時廣播「請重新註冊」並等待。

  • ★ 多個路由器實例要共享路由表,否則同樣的訊息隨機去不同地方;而共享儲存又是新的單點。

  • ★ 註冊要驗證身分、目的地要白名單。任意註冊 = 可以把別人的訊息導給自己。

  • ★ RabbitMQ 的 binding 機制已經免費提供了整套「目的地自己註冊」(含斷線自動移除)。

  • 這是路由家族裡最少用到、也最容易過度設計的一個。 先確認 broker 的訂閱機制真的不夠。

🔗 相關工具