事件驅動系統中不同型別的事件 - frankdejonge
事件驅動系統有各種形狀和大小。明顯的共同點是;他們都使用事件來傳達資訊。這些事件有多種形式和大小,確定事件中的內容會對系統設計產生巨大影響。
在這篇文章中,我想討論三種不同型別的事件。我希望澄清這些型別將使您能夠更好地討論事件驅動的架構和整合。
三種事件原型
當我與其他開發人員討論事件時,我區分了三種型別的事件。每種型別都有其獨特的特徵、優勢和劣勢。這些型別的事件都不一定比另一種更好,但在特定情況下,特定型別可能更適合。
這些型別的事件是:
- 領域事件
- 觸發或訊號事件
- RESTful 或“胖”事件
讓我們逐一介紹它們,看看它們是什麼,以及它們何時有用。
領域事件
對於任何對領域驅動設計感興趣的人來說,這將是最熟悉的事件型別。領域事件是歷史的記錄,捕捉重要時刻的意圖和任何相關上下文。領域事件關注“領域”,這意味著它們關注與業務相關的事物。因為他們記錄歷史,所以他們用過去時表達。
下圖是事件之間的因果與相關性關係:
領域事件以明確表達意圖的方式命名。建議使用人類語言來命名這些事件,儘量避免使用“嗶嗶”語言。而不是命名事件OrderStateChanged或OrderEvent,使用類似的東西OrderWasShipped。
與其他事件型別不同,域事件非常適合捕獲意圖。因為領域事件只捕捉重要時刻的相關上下文,所以它們也非常適合捕捉變化。這讓活動消費者對正在發生的事情有了深刻的瞭解。事件源系統更進一步,使領域事件成為軟體模型的基石。
領域事件特別適合用於建立讀取模型。在讀取用例要求與有助於做出決策的資料模型非常不同的情況下。在建立讀取模型和分析資料模型中,以更改和意圖為中心的表示非常適合聚合。
class OrderWasShipped { public function __construct( private OrderId $orderId, private MomentOfSchipment $shippedAt, private ShipmentAddresss $shipmentAddress, ); public function orderId(): OrderId { return $this->orderId; } public function shippedAt(): MomentOfSchipment { return $this->skippedAt; } public function shipmentAddress(): ShipmentAddresss { return $this->shipmentAddress; } } |
- 優點
領域事件非常適合捕捉意圖和“變化”。它們允許您構建強大的讀取模型,其擴充套件性比原始資料模型上的複雜查詢要好得多。領域意圖對於建立分析模型非常強大,它可以提供對業務中正在發生的事情的深刻見解。
- 缺點
域事件暴露了域內部發生的事情。如果消費者依賴此資訊,他們就會與之耦合。如果使用領域事件來建立決策模型,那麼這些事件的耦合會對開發速度造成壓力。耦合增加了改變的成本,所以知道你暴露了什麼以及暴露給誰總是好的。作為預設做法,將每個域事件視為“私有”,僅用於內部使用。只有透過故意曝光,消費者才能訪問事件,類似於使用 API 而非直接訪問資料庫的方式。
觸發或訊號事件
觸發或訊號事件是最小的事件。此事件通常僅包含一個引用聚合或實體的 ID,也可能包含時間戳。正如名稱觸發器所暗示的,這些事件用於觸發消費方的反應。觸發器最常用於通知其他業務流程發生變化。在您儲存敏感資料的情況下(看看您,GDPR),使用觸發器可以幫助防止將事件基礎設施暴露於具有挑戰性的要求。
class OrderWasShipped { public function __construct( private OrderId $orderId ); public function orderId(): OrderId { return $this->orderId; } } |
- 優點
當域事件可能包含敏感資料時,觸發器很有用。在這些情況下,生產者發出一個訊號並期望消費者使用安全的 API 來獲取相應的 ID。觸發器不容易引起資訊級耦合,僅僅是因為它們不包含任何內容。
- 缺點
由於觸發器不包含任何資訊,因此消費者總是依賴於 API。當許多消費者消費許多事件時,這可能會給您的系統帶來一些意想不到的負載。資訊的缺失也限制了彙總資料的能力。
由於事件是非同步處理的,因此從 API 檢索的資料可能處於消費者期望的不同狀態。消費者必須始終檢查從 API 檢索的資源是否是他們所期望的,並準備好處理資源可能處於的任何可能狀態。例如,如果訂單已發貨,但商家立即取消發貨,則消費者可能會檢索到與事件名稱所暗示的狀態不匹配的貨運資源。當發生事件處理延遲時,這可能會產生意想不到的結果。
RESTful 或“胖”事件
最後一個原型是“胖”事件。我個人更喜歡術語 RESTful 事件,因為它更好地描述了有效負載中的內容。這種型別的事件包含您將從 RESTful API 檢索到的完整資源表示。這是一個很好的整合活動,對外部消費者最有用。
與觸發器相比,RESTful 事件阻止消費者往返 API。如果將其與域事件進行比較,它可以防止消費者不得不組合多個事件來獲得完整的畫面。
class OrderWasShipped { public function __construct( private OrderId $orderId, private OrderLines $orderLines, private DiscountCodes $discountCodes, private OrderAmount $orderAmount, private MomentOfSchipment $shippedAt, private ShipmentAddresss $shipmentAddress, ); public function orderId(): OrderId { return $this->orderId; } public function orderLines(): OrderLines { return $this->orderLines; } public function discountCodes(): DiscountCodes { return $this->discountCodes; } public function orderAmount(): OrderAmount { return $this->orderAmount; } public function shippedAt(): MomentOfSchipment { return $this->skippedAt; } public function shipmentAddress(): ShipmentAddresss { return $this->shipmentAddress; } } |
- 優點
RESTful 事件非常適合將狀態推送給消費者。在一個事件中,消費者對資源瞭如指掌。對於每個資源,只需將最後一個事件備份到最新狀態,這對於災難恢復非常有用。如果另一個服務依賴於您的服務的狀態,則使用 RESTful 事件是一種將狀態推送到那裡的好方法。在最終一致性可以接受的情況下,這樣做將消除對服務的直接依賴。
- 缺點
根據我的經驗,RESTful 事件僅作為“外部”消費者的整合工具有用。它們對內部建模沒有用處。它們很大,更匿名,傳達的意圖較少,因此不太適合內部建模。RESTful 事件通常需要您構建一個防損壞層來將其他型別的事件轉換為 RESTful 事件,這是“額外”的工作。
就事件進行有意義的討論
在技術討論中,很容易跳到解決方案上。只需新增該欄位,只需將此內部事件公開給外部消費者,即可解決問題。我希望透過確定幾種型別的事件,您可以將這些資訊帶入您正在進行的討論中。嘗試確定計劃中的事件型別,它們具有哪些特徵,以及這些特徵如何影響您應用它們的情況。暴露領域事件?注意資訊級耦合。因為消費者需要它們而將越來越多的資訊新增到事件中?也許切換到 RESTful 事件。最後,請記住,如果在正確的環境中應用不同的溝通方式,效果最好。您應該意識到這一點並做出正確的選擇。
相關文章
- 事件驅動的微服務-事件驅動設計事件微服務
- Redis 中的事件驅動模型Redis事件模型
- 無伺服器事件驅動系統伺服器事件
- 事件驅動系統設計之將事件檢索與事件處理解耦事件解耦
- RocketMQ 事件驅動:雲時代的事件驅動有啥不同?MQ事件
- 事件驅動架構EDA中的元件事件架構元件
- 混合雲中的事件驅動架構事件架構
- Spring中的事件驅動模型(一)Spring事件模型
- Repository的事件驅動事件
- Spring:事件驅動Spring事件
- 我對事件驅動的理解事件
- Javascript中的事件物件和事件型別JavaScript事件物件型別
- 事件驅動程式設計事件程式設計
- 如何在Java後端中實現事件驅動架構:從事件匯流排到事件溯源Java後端事件架構
- 精簡化事件:事件驅動架構的精益力量事件架構
- spring — Spring中的事件驅動機制解析Spring事件
- 事件系統-z 事件發現事件
- 事件驅動及其設計模式事件設計模式
- 事件驅動架構設計事件架構
- 事件驅動,Do you know?事件
- Java開發中的事件驅動模型例項詳解Java事件模型
- [譯] 理解 NodeJS 中基於事件驅動的架構NodeJS事件架構
- Oracle事件驅動的排程作業Oracle事件
- “訊息驅動、事件驅動、流 ”基礎概念解析事件
- 全鏈路營銷|基於事件驅動的流程編排系統 策略中心繫統事件
- Laravel 事件系統Laravel事件
- 【譯】理解Node事件驅動架構事件架構
- 小馬哥Spring事件驅動模型Spring事件模型
- 如何在Java中實現事件驅動的微服務架構Java事件微服務架構
- Netty背後的事件驅動機制Netty事件
- 基於 Redis驅動的 Laravel 事件廣播RedisLaravel事件
- 一個事件驅動的圖片爬蟲事件爬蟲
- Henry的VB.NET之旅(十二)—事件驅動事件
- 事件驅動的元件框架Flight介紹事件元件框架
- 基於事件驅動的測試框架ETS事件框架
- Laravel事件系統的使用Laravel事件
- 基於事件溯源與CDC的事件驅動微服務架構案例原始碼事件微服務架構原始碼
- 基於spring實現事件驅動Spring事件