🎯 什麼情境該想到我

當你「只想讓符合條件的訊息通過,其餘直接丟棄」的時候。

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

意圖:從通道中剔除不感興趣的訊息。

做法要點:

  • 過濾器檢查每一則訊息是否符合條件。
  • 符合就原樣轉出;不符合就丟棄。
  • 是「只有單一輸出、且輸出為零或一則」的特例路由。
  • 常用於發布訂閱情境,讓各接收端只留下自己關心的訊息。

★★ 最重要的決定:過濾應該發生在哪一端

① ★ 生產端不發    → 最省(零網路、零處理),但生產者要知道「誰不要什麼」
② ★★ broker 過濾  → 最佳:省網路、零額外元件
                     RabbitMQ topic exchange/headers exchange、SNS filter policy、NATS 通配
③ 獨立的過濾器元件 → ★ 多一跳、多一個部署單元
④ ★ 消費端過濾    → 最簡單,但白收所有訊息(見 [[選擇性消費者]])

★★ 順序就是這個順序。 先問 ①②,再考慮 ③。
★ Kafka 特別注意:它沒有 broker 端過濾(除了分區),所以在 Kafka 上
「過濾」只有 ① 和 ④——要嘛分流成不同 topic,要嘛消費端全收再丟。

④ 的成本可以估算:

訊息 2 KB × 每秒 10,000 則 × 只有 5% 有用
→ ★ 白收 19 MB/s 的網路 + 反序列化 CPU
→ 值不值得加一個過濾器元件?★ 自己算,不要憑感覺

★★ 這個模式最大的風險:丟掉的訊息沒有痕跡

// ❌ 靜默丟棄 —— 過濾器與 bug 長得一模一樣
if !match(e) { return msg.Ack() }
 
// ✅ 至少要有指標;高價值訊息還要有紀錄
if !match(e) {
    metrics.Filtered.WithLabelValues(e.Type, reason(e)).Inc()   // ★ 帶原因的標籤
    return msg.Ack()
}

★★ 「為什麼那筆訂單沒進來」最難查的情況,就是它被某個過濾器丟掉了——
因為沒有錯誤、沒有日誌、沒有痕跡。
★ 過濾器和「有 bug 的路由器」在外部觀察上完全無法區分。

★ 對策的三個層次:
① 一定要有帶原因標籤的計數器(最低要求)。
② 高價值訊息:丟棄前寫一筆紀錄(誰、為什麼、什麼時候)。
③ ★ 可疑時改成「導流」而非「丟棄」:送到一條 filtered.orders 通道
(這就是 繞道)——留著,但不進主流程。

★ 過濾條件的維護:這是長期的痛點

// ★ 條件要是純函式 + 有測試 —— 它是業務規則,不是設定
func shouldProcess(e Envelope) (bool, string) {
    if e.Region != "TW" { return false, "region" }        // ★ 回傳原因,用於指標
    if e.Amount < minAmount { return false, "below_min" }
    return true, ""
}

⚠️ 兩個常見的腐敗:

  1. ★ 條件累積成沒人敢改的一團:if a && !b && (c || d) && !e ——
    每一項都是某次事故留下的補丁,而沒有人記得為什麼。
    → ★ 每個條件旁邊註記「為什麼」與「什麼時候可以拿掉」(見 註釋 的第③類)。
  2. ★ 過濾條件散落在多個元件:生產者過一次、broker 過一次、消費者再過一次
    → 「這筆為什麼沒到」要查三個地方。盡量只在一處過濾。

★ 兄弟辨析

差別
內容路由器★ 不符條件的訊息去另一個通道;過濾器直接丟掉
選擇性消費者★ 同一件事發生在消費端(消費者只挑自己要的)
繞道★ 把訊息導去別處而不是丟掉——★ 通常是過濾器更好的替代
內容過濾器★★ 名字像但完全不同:它移除訊息裡的欄位,不是丟掉整則訊息

🧪 我實際套用的紀錄

  • (待填)

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

  • 與內容路由器不同:過濾器可能完全不輸出(把訊息丟掉)。

  • 若過濾邏輯分散在多個接收端,可考慮改用內容路由器集中控管。

  • 被丟棄的訊息通常不保留,需要留存時要另做處理。

  • ★★ 過濾順序:生產端不發 > broker 過濾 > 獨立元件 > 消費端過濾。 先問前兩個。

  • ★ Kafka 沒有 broker 端過濾。只能分流成不同 topic,或消費端全收再丟。

  • ★★ 靜默丟棄的過濾器和有 bug 的路由器無法區分。 至少要有帶原因標籤的計數器。

  • ★ 可疑時改成「導流」而非「丟棄」(繞道)——留著但不進主流程。

  • ★ 過濾條件會累積成沒人敢改的一團。每個條件旁註記「為什麼」與「何時可拿掉」。

  • ★ 不要在多處過濾。散落三個地方時,「這筆為什麼沒到」要查三次。

  • 消費端過濾的成本可以估算(訊息大小 × 速率 × 丟棄比例)。用數字決定要不要加元件,不要憑感覺。

  • ★ 不要和 內容過濾器 搞混:那個移除欄位,這個丟掉整則訊息。

🔗 相關工具