文章三:⚔️ Resilience Isn’t Optional: Event-First APIs in Modern .NET

這篇文章有力地論證了在現代 .NET 分散式系統中採用「事件優先」(Event-First)架構的必要性,以對抗純同步 RESTful API 的內在脆弱性。

RESTful API 的沈默殺手與思維轉變

本節介紹了分散式系統中的「沈默殺手」:由標準 RESTful API 所創造的成功假象。一個 200 OKPOST 回應往往掩蓋了底層的數據混亂,例如重複收費或庫存不一致。作者提出了從協調(Orchestration)到觸發(Triggering)的根本性思維轉變。API 端點不應同步執行整個業務工作流程,而應承擔單一職責:可靠地發出一個表示「行動意圖」的事件。這種方法是事件優先架構的核心,它將 API 與下游流程解耦,使其能夠以自己的重試邏輯和故障恢復機制非同步地處理各自的職責。

事件優先的原則與 .NET 實作

本節概述了事件優先思維的核心原則。中心思想是,API 的主要職責不是完成一個流程,而是將客戶端的意圖作為一個不可變的事件(例如 OrderInitiated)持久化。這個事件成為原子性的結果和事實的來源。所有後續工作——處理付款、發送電子郵件——都由消費此事件的獨立服務非同步處理。API 則可以立即回應 HTTP 202 Accepted,表示請求已收到,而非已完成。

文章提供了一個實用的 .NET 實作指南,展示了一個 OrdersController,其唯一職責是驗證傳入的請求並持久化用戶意圖。它透過創建一個命令物件並將其傳遞給一個實現了發送箱模式(Outbox Pattern) 的服務來完成此操作。CommandService 會序列化此命令,並將其作為 OutboxMessage 記錄保存到主應用程式資料庫中,此操作與任何初始業務狀態變更在同一個原子資料庫事務中執行。

發送箱處理器與關鍵架構模式

本部分詳細介紹了發送箱模式的後半部分:OutboxProcessor。作為一個 .NET BackgroundService 實現,這個處理器在背景持續運行。它的工作是輪詢資料庫中的 OutboxMessages 表,查找未處理的記錄。對於找到的每條訊息,它會反序列化事件負載,並透過像 IEventBus 這樣的抽象將其發布到訊息代理。

為了建立穩健的事件驅動系統,文章還強調了幾個關鍵的架構模式:

混合架構與不適用場景

文章提倡一種務實的混合架構,而非完全廢除 REST。REST 對於同步的請求-回應場景(如數據檢索 GET 請求)仍然非常有效。真正的威力在於結合兩種模式的優點:對同步查詢使用 REST 的簡潔性,對觸發複雜、長時間運行或易於失敗的非同步工作流程的命令使用事件優先模式(以 HTTP 202 Accepted 回應並發布事件)。

同時,作者也審慎地指出了事件優先架構不適用的場景:

整篇文章重點結論

本文為在現代 .NET 分散式系統中採用「事件優先」架構提供了一個強有力的論證,以對抗純同步 RESTful API 的內在脆弱性。它首先指出了「沈默殺手」:HTTP 200 OK 並不代表業務操作的完整成功。文章提出的解決方案是一種思維和架構上的轉變:API 的角色應該是捕捉用戶意圖為事件,並立即返回 HTTP 202 Accepted,將實際工作卸載給具備韌性的非同步背景消費者。

文章提供了使用 發送箱模式(Outbox Pattern) 在 .NET 中實現的全面指南,並涵蓋了如 冪等消費者事件版本控制死信佇列等關鍵支持模式。最後,它提倡一種務實的混合方法,並明確了不應使用此模式的場景。這是一份關於如何建構具備韌性、可擴展和可維護的分散式系統的實踐指南。