通訊的第一個決定不是「用什麼技術」,是「用什麼樣式」:同步阻塞簡單、但把服務綁在同一條時間線上;非同步解耦了時間、代價是複雜度。先選樣式,再讓樣式去篩技術。
🧠 Core Ideas
TIP
兩步決策:先問同步還是非同步,再問請求-回應還是事件驅動。倒過來「先選技術」——硬把 Kafka 拿去做請求-回應、或凡事都 REST——就是多數通訊層踩雷的起點。
- 同步阻塞:送出請求後卡住等回應。心智模型最熟(就像本地方法呼叫、SQL 查詢)。
- 非同步非阻塞:送出後可以繼續做別的;時間解耦,兩端不必同時在線。
- 「跨行程」不等於「行程內」:跨網路呼叫是毫秒級、要序列化、錯誤一大堆(逾時、下游掛、被 OOM)——別把遠端呼叫當本地方法設計。
⚖️ Tradeoffs
同步阻塞 — 簡單,但會級聯失敗
- 與下游時間耦合:對方必須在線,對方慢你就跟著慢。
- 呼叫鏈一長最危險:
Order → Payment → Fraud → Customer,任一環卡住整條鏈掛掉,還會把連線耗盡、塞爆網路(級聯失敗)。 - 解法之一是重組流程——把非關鍵步驟(如詐欺偵測)移出主鏈、改背景處理,縮短關鍵路徑。
非同步 — 解耦時間,但心智負擔高
- 適合長時間工作:通知倉庫出貨,揀貨包裝要好幾小時,同步等顯然不行。
- 也適合高吞吐、難重組的長鏈路。
- 代價:async 風格與訊息技術選擇一大堆,容易踩非同步特有的坑(見下)。
請求-回應 vs 事件驅動(責任反轉)
- 請求-回應:期待對方回覆;同步、非同步都能做。非同步版要處理「回應送回哪」與「把回應對回原始請求」(常存 DB 再重載)。
- 事件驅動:發佈「已發生的事實」,發佈者不知道誰在聽。這是責任反轉——不是「倉庫命令通知服務寄信」,而是「倉庫廣播事件,通知服務自己決定要不要寄」。最鬆耦合,也最契合自治團隊。
- 事件裡放什麼?只放 ID → 訂閱者得回頭問來源,增加耦合、還可能把來源打爆;放完整資訊 → 訂閱者自給自足,但事件變成對外契約、要留意 PII 擴散。
非同步的坑:一定要先想好
- 訊息有毒 → worker 一個個爆、佇列又把訊息還回去 → 下一個接到也死(「災難性故障轉移」)。
- 必備:最大重試次數、死信佇列、失敗訊息的檢視/重送、跨服務追蹤的關聯 ID(correlation ID)。
- 事件驅動要「笨中間件、聰明端點」——別讓中間件(ESB)長出一堆邏輯。
- 順帶一提:輪詢很浪費(研究顯示只有約 1.5% 的輪詢真的拿到新資料),要即時推送改用 WebHooks / WebSockets / SSE。
🔑 Takeaways
- 先選樣式(同步/非同步 → 請求-回應/事件驅動)再選技術,別反過來。
- 同步阻塞簡單但級聯失敗是頭號風險;鏈路一長就想辦法重組或轉非同步。
- 事件驅動最鬆耦合,但死信佇列、重試上限、關聯 ID 是入場券,缺一不可(延伸自重試與退避)。
No notes yet — jot your takeaways or Q&A here.