天天看點

DDD領域驅動設計實戰(六)-了解領域事件(Domain Event)(上)1 when and why使用領域事件?

  • 如何将領域事件模組化成對象,何時應該為領域事件建立唯一的身份辨別?
  • 哪些元件用于釋出事件,哪些元件用于訂閱事件
  • 為什麼我們需要一個事件存儲?如何實作事件存儲、如何使用事件存儲?
  • 如何通過不同的方式将領域事件釋出給自治系統

1 when and why使用領域事件?

1.1 定義

使用領域事件時,首先就是要對不同僚件進行定義。

《領域驅動設計》并未給出領域事件的定義,因為該模型是在該書出版後才被提出。

目前對領域事件的定義:領域專家所關心的發生在領域中的一些事件。将領域中所發生的活動模組化成一系列的離散事件。

每個事件都用領域對象來表示,領域事件是領域模型的組成部分,表示領域中所發生的事情。

如何确定哪些事件對領域專家重要?

1.2 識别領域事件

  • “當……”
  • “如果發生……,則……”
  • “當做完……的時候,請通知……”
  • 這裡的通知本身并不構成一個事件,隻是表明我們需要向外界發出通知.

在這些場景中,若發生某種事件後,會觸發進一步操作,則該事件很可能就是領域事件。

有時從領域專家話中,好像也還看不出哪裡有領域事件,但業務需求依然可能需要領域事件。領域專家有時可能意識不到這些需求,隻有在經過跨團隊讨論後才意識到這些。

之是以會這樣,是由于領域事件需釋出到外部系統,如到另一個限界上下文。由于這樣的事件由訂閱方處理,它将對本地和遠端上下文都産生影響。

由于領域事件需要釋出到外部系統,如釋出到另一個限界上下文。這樣的事件由訂閱方處理,影響本地和遠端上下文。

一個領域事件将導緻進一步業務操作,在實作業務解耦同時,還有助于形成完整的業務閉環。

領域事件可以是業務流程的一個步驟,如一個事件發生後觸發的後續動作:密碼連續輸錯三次,觸發鎖定賬戶的動作。

領域事件為何要用最終一緻性,而非SOA直接調用?

因為聚合的一個原則:一個事務中最多隻能更改一個聚合執行個體,是以:

  • 本地限界上下文中的其他聚合執行個體,可通過領域事件的方式同步
  • 用于使遠端依賴系統與本地系統保持一緻

解耦本地系統和遠端系,有助提高雙方協作服務的可伸縮性

DDD領域驅動設計實戰(六)-了解領域事件(Domain Event)(上)1 when and why使用領域事件?

聚合建立并釋出事件

  • 訂閱方可先存儲事件,然後再将其轉發到遠端訂閱方
  • 或不經存儲,直接轉發

    除非MQ共享了模型的資料存儲,不然即時轉發需要XA(兩階段送出)。

  • 系統業務低峰期,批處理過程通常進行一些系統維護工作,如删除過期對象、建立新對象以支援新業務需求或通知使用者所發生的重要事件。

這樣的批處理過程通常需複雜查詢&&龐大事務。若這些批處理過程存在備援會怎樣?

系統中發生的每一件事情,都用事件形式捕獲,然後将事件釋出給訂閱方處理,能簡化系統嗎?

肯定的!它可消除先前批處理過程中的複雜查詢,因為我們能夠準确知道在何時發生何事,限界上下文也由此知道接下來應該做啥。在接收到領域事件時,系統可立即處理。原本批量集中處理的過程可以分散成許多粒度較小的處理單元,業務需求也由此更快滿足,使用者也可及時進行下一步操作。

領域事件驅動設計可切斷領域模型之間的強依賴。

事件釋出完成後,釋出方不必關心後續訂閱方事件處理是否成功,即可實作領域模型的解耦,維護領域模型的獨立性和資料一緻性。

在領域模型映射到微服務架構時,領域事件可解耦微服務,微服務間的資料不必要求強一緻性,而是基于事件的最終一緻性。