精簡化事件:事件驅動架構的精益力量

公众号-JavaEdge發表於2024-08-24

精簡化事件:事件驅動架構的精益力量

在軟體開發領域,事件驅動架構(Event-Driven Architecture,簡稱 EDA)因其促進實時通訊、具有良好的可擴充套件性以及構建松耦合系統的能力,越來越受到重視。其核心思想是透過事件來實現通訊。在使用事件驅動架構的過程中,關於事件的設計一直存在爭議:我們應該採用“詳細事件”還是“簡單事件”?

至今沒固定答案;兩者在特定情況下各有優勢。但根據我的經驗,簡單事件通常更能使軟體執行平穩且具有靈活性。以下是我對這個問題的解釋。

1 簡單事件與詳細事件:選擇合適的傳遞者

以使用者註冊場景為例:

詳細事件

使用者註冊場景中,詳細事件會包含全面而詳細的資料。這可能包括姓名、地址、偏好設定甚至頭像等所有資訊。這些資料非常豐富——但是,我們真的需要立即獲取所有這些資訊嗎?

簡單事件

同樣在這個場景中,簡單事件可能只是一個通知,僅包含使用者 ID。它有效地傳達了核心資訊——如果需要更多細節,可以稍後查詢。

可將簡單事件(有時稱為“事件通知”)比作電報,用最少的資料傳遞關鍵資訊,下游系統可以根據需求再獲取具體細節。
而詳細事件(有時稱為“胖事件”或“事件攜帶的狀態傳輸”)更像是一份詳盡的報告。它們一開始就攜帶了大量資料,可能包含了你可能需要的所有資訊。可以將其視為使用者註冊的詳盡報告。

2 不止是傳遞:事件協調系統

在事件驅動架構中,事件的作用不僅僅是傳遞訊息;它們還在系統中引發一系列動作。透過非同步通訊,事件使得系統的不同部分可以獨立運作並動態響應,從而實現松耦合。松耦合意味著系統的各個部分可以獨立運作和修改,而不必依賴於其他部分的內部運作。非同步通訊允許系統各部分在不等待即時響應的情況下進行互動。這種通訊方式的好處在於,它支援獨立操作和動態響應,使系統能夠實時響應事件,而不會因其他程序而受阻。
事件的主要價值在於它告知系統何時發生了某個動作,並幫助系統保持靈活性、可擴充套件性和穩定性。它們讓系統的其他部分知道某個變化已發生,從而觸發其他流程。例如,一個“商品購買”事件將觸發庫存更新、訂單確認和發貨通知等動作。在 EDA 中,這些動作協同工作。

3 簡單事件:EDA 的靈活核心

在事件驅動架構中,簡單事件因其簡潔、模組化和適應性而非常有用。以下是簡單事件之所以重要的原因:

明確的界限

可將簡單事件比作幕後工作人員,確保表演過程中的平穩過渡。它們宣佈動作——例如“使用者評論”——但將資料收集的任務留給專家:API。透過明確任務之間的界限,簡單事件促進了模組化。這意味著系統可以獨立發展,而不會對整體效能產生負面影響。如果通知系統收到“使用者評論”事件,這已經足夠啟動通知流程;它不需要知道使用者的姓名或頭像等資訊。有了明確的界限和溝通,系統就能和諧地執行。

無特定依賴,適應性強

簡單事件具有多功能性;它們可以適應不同的需求。即使消費者數量增加或事件消費的目的隨時間演變,它們也能順利擴充套件。例如,“使用者更新個人資料”事件並不關心新系統是否需要這些資料用於營銷——它只是傳遞核心資訊。這種適應性確保了事件在不斷變化的消費者環境中仍然保持相關性和高效性。

平衡之道

詳細事件在資料粒度和效率之間往往難以取得平衡。決定包含哪些資訊總是一個在資訊量與負載大小之間權衡的問題。而簡單事件則避免了這個問題,因為它們優先考慮簡化通訊。這意味著它們可以避免過大的負載和複雜且不斷變化的資料結構。

4 詳細事件:針對特定問題的策略性使用

儘管簡單事件在事件驅動架構中具有許多優勢,但在某些特定情況下,詳細事件仍然有其價值,特別是在需要預先包含資料的情況下。以下是詳細事件可能有用的一些情況:

整合事件

設想你正在嘗試將支付系統整合到你的平臺中。共享的上下文可能有限,因此無縫通訊至關重要。在這種情況下,一個設計良好的詳細事件,包含訂單詳情和支付資訊,可以彌補這一差距,確保資料順利交換。

特定時刻的狀態

在資料頻繁變化的動態領域,消費者通常需要特定時刻的準確資料,比如在嘗試捕捉支付資訊或通知內容時。透過在事件中包含所有必要資料,可以更好地確保後續的準確呈現。例如,如果一個“支付處理”事件需要包括交易金額、餘額和貨幣資訊以進行準確處理,那麼它可能需要是一個詳細事件。

注意事項

  • 在大型應用程式中,使用詳細事件可能不太理想,但在事件消費者與事件生產者位置相近的小型解決方案中,可以考慮使用詳細事件。在這種情況下,生產者應
  • 清楚消費者的資料需求,並且確信暴露過多資料不會帶來安全風險。然而,隨著解決方案的發展,定期重新審視這些假設是至關重要的。

5 DDD 與詳細事件:走鋼絲

在事件驅動架構中,關於詳細事件應該包含哪些資料存在一種兩難選擇:我們應該為整個聚合體新增資料,還是隻為聚合體中的一個實體新增資料?這就是所謂的實體與聚合資料包含困境。在領域驅動設計(DDD)中,實體和聚合是兩個基本且相關的概念。實體是具有唯一標識和明確定義行為的個體物件;聚合是由實體組成的一致性集合。聚合通常代表一個完整的業務行為單元。
嵌入實體級資料意味著包括特定於聚合體內單個實體的細粒度資訊。雖然這種方法提供了詳細的資訊,但如果在聚合體中引用了多個實體,它可能會導致事件數量的增加。這種複雜性使得管理模式變化變得困難,並可能違反 DDD 的封裝原則。
另一方面,嵌入聚合級資料則意味著包含代表整個聚合體狀態或其中相關實體的資料。雖然這種方法可以防止事件數量的膨脹,但它可能會過度暴露並非所有消費者都需要的細節,從而可能導致系統之間的緊耦合。例如,如果消費系統接收到包含超出其實際需求的詳細資訊的聚合級資料,它可能會開始依賴這些額外的細節。這會建立一種依賴性,使消費系統與生產系統的實現細節緊密耦合。
此外,關於資料隱私也存在潛在的擔憂;資料可能會暴露給不應訪問它的消費者。然而,API 應該能夠很好地處理此類場景,提供對資料訪問的控制和安全層,並確保遵守隱私法規。

6 設計權衡

在事件驅動架構中選擇使用詳細事件還是簡單事件時,有許多值得考慮的因素。

  • 偏向最小資料:從觸發下游操作所需的最少資訊開始。不要在事件中新增不必要的細節。
  • 利用 API 獲取詳細資料訪問:允許消費者透過定義良好的 API 檢索他們需要的具體資料,遵循關注點分離原則。
  • 仔細評估詳細事件,列出具體需求,並在複雜性與收益之間進行權衡。記錄你選擇背後的原因,以備將來參考。
  • 將資料包含放在上下文中:如果不可避免地需要嵌入資料,請仔細考慮具體的使用場景。

7 結論

儘管詳細事件有其適用的場景,但簡單事件的簡潔性和靈活性使它們成為大多數事件驅動架構設計中的首選。簡單事件透過關注簡化、模組化和明確的職責劃分,使系統能夠順利增長並適應不斷變化的需求,而不影響其穩定性或效率。

然而,我們需要記住的是,沒有一種解決方案適用於所有情況。根據你的具體情況、資料需求和通訊要求做出明智的選擇。不斷嘗試,積累經驗,並充分利用事件驅動架構的潛力,以構建強大且靈活的系統。

關注我,緊跟本系列專欄文章,咱們下篇再續!

作者簡介:魔都架構師,多家大廠後端一線研發經驗,在分散式系統設計、資料平臺架構和AI應用開發等領域都有豐富實踐經驗。

各大技術社群頭部專家博主。具有豐富的引領團隊經驗,深厚業務架構和解決方案的積累。

負責:

  • 中央/分銷預訂系統效能最佳化
  • 活動&券等營銷中臺建設
  • 交易平臺及資料中臺等架構和開發設計
  • 車聯網核心平臺-物聯網連線平臺、大資料平臺架構設計及最佳化
  • LLM Agent應用開發
  • 區塊鏈應用開發
  • 大資料開發挖掘經驗
  • 推薦系統專案

目前主攻市級軟體專案設計、構建服務全社會的應用系統。
本文由部落格一文多發平臺 OpenWrite 釋出!

相關文章