目錄
1、概述
2、領域事件
2.1 如何識別領域事件
1.微服務內的領域事件
2.微服務之間的領域事件
3、領域事件總體架構
3.1 事件構建和發(fā)布
3.2 事件數據持久化
3.3 事件總線 (EventBus)
3.4 消息中間件
3.5 事件接收和處理
4、案例
5、總結
1、概述
在事件風暴(Event Storming)時,我們知道除了命令和操作等業(yè)務行為以外,還有一種非常重要
的事件,這種事件發(fā)生后通常會導致進一步的業(yè)務操作,在DDD中這種事件被稱為領域事件。
那到底什么是領域事件?領域事件的技術實現機制是怎樣的?
2、領域事件
領域事件是領域模型中非常重要的一部分,用來表示領域中發(fā)生的事件。一個領域事件將導
致進一步的業(yè)務操作,在實現業(yè)務解耦的同時,還有助于形成完整的業(yè)務閉環(huán)。
舉例來說的話,領域事件可以是業(yè)務流程的一個步驟,比如投保業(yè)務繳費完成后,觸發(fā)投保
單轉保單的動作;也可能是定時批處理過程中發(fā)生的事件,比如批處理生成季繳保費通知
單,觸發(fā)發(fā)送繳費郵件通知操作;或者一個事件發(fā)生后觸發(fā)的后續(xù)動作,比如密碼連續(xù)輸錯
三次,觸發(fā)鎖定賬戶的動作。
2.1 如何識別領域事件
在做用戶旅程或者場景分析時,我們要捕捉業(yè)務、需求人員或領域專家口中的關鍵詞:“如果發(fā)
生……,則……”“當做完……的時候,請通知……”“發(fā)生……時,則……”等。
在這些場景中,如果發(fā)生某種事件后,會觸發(fā)進一步的操作,那么這個事件很可能就是領域事件。
那領域事件為什么要用最終一致性,而不是傳統SOA的直接調用的方式呢?
聚合的一個設計原則:在邊界之外使用最終一致性。
一次事務最多只能更改一個聚合的狀態(tài)。如果一次業(yè)務操作涉及多個聚合狀態(tài)的更改,應采用領域
事件的最終一致性。
領域事件驅動設計可以切斷領域模型之間的強依賴關系,事件發(fā)布完成后,發(fā)布方不必關心后續(xù)訂
閱方事件處理是否成功,這樣可以實現領域模型的解耦,維護領域模型的獨立性和數據的一致性。
在領域模型映射到微服務系統架構時,領域事件可以解耦微服務,微服務之間的數據不必要求強一
致性,而是基于事件的最終一致性。
1.微服務內的領域事件
當領域事件發(fā)生在微服務內的聚合之間,領域事件發(fā)生后完成事件實體構建和事件數據持久化,發(fā)
布方聚合將事件發(fā)布到事件總線,訂閱方接收事件數據完成后續(xù)業(yè)務操作。
微服務內大部分事件的集成,都發(fā)生在同一個進程內,進程自身可以很好地控制事務,因此不一定
需要引入消息中間件。但一個事件如果同時更新多個聚合,按照DDD“一次事務只更新一個聚合”的
原則,你就要考慮是否引入事件總線。
微服務內應用服務,可以通過跨聚合的服務編排和組合,以服務調用的方式完成跨聚合的訪問,這
種方式通常應用于實時性和數據一致性要求高的場景。這個過程會用到分布式事務,以保證發(fā)布方
和訂閱方的數據同時更新成功。
2.微服務之間的領域事件
跨微服務的領域事件會在不同的限界上下文或領域模型之間實現業(yè)務協作,其主要目的是實現微服
務解耦,減輕微服務之間實時服務訪問的壓力。
跨微服務的事件機制要總體考慮事件構建、發(fā)布和訂閱、事件數據持久化、消息中間件,甚至事件
數據持久化時還可能需要考慮引入分布式事務機制等。
微服務之間的訪問也可以采用應用服務直接調用的方式,實現數據和服務的實時訪問,弊端就是跨
微服務的數據同時變更需要引入分布式事務,以確保數據的一致性。分布式事務機制會影響系統性
能,增加微服務之間的耦合,所以我們還是要盡量避免使用分布式事務。
總之,通過領域事件驅動的異步化機制,可以推動業(yè)務流程和數據在各個不同微服務之間的流轉,
實現微服務的解耦,減輕微服務之間服務調用的壓力,提升用戶體驗。
3、領域事件總體架構
領域事件的執(zhí)行,需要一系列的組件和技術來支撐。領域事件處理包括:事件構建和發(fā)布、事件數
據持久化、事件總線、消息中間件、事件接收和處理等。
3.1 事件構建和發(fā)布
事件基本屬性至少包括:事件唯一標識、發(fā)生時間、事件類型和事件源,其中事件唯一標識應該是
全局唯一的,以便事件能夠無歧義地在多個限界上下文中傳遞。事件基本屬性主要記錄事件自身以
及事件發(fā)生背景的數據。
另外事件中還有一項更重要,那就是業(yè)務屬性,用于記錄事件發(fā)生那一刻的業(yè)務數據,這些數據會
隨事件傳輸到訂閱方,以開展下一步的業(yè)務操作。
事件基本屬性和業(yè)務屬性一起構成事件實體,事件實體依賴聚合根。領域事件發(fā)生后,事件中的業(yè)
務數據不再修改,因此業(yè)務數據可以以序列化值對象的形式保存,這種存儲格式在消息中間件中也
比較容易解析和獲取。
為了保證事件結構的統一,我們還會創(chuàng)建事件基類DomainEvent,子類可以擴充屬性和方法。由
于事件沒有太多的業(yè)務行為,實現方法一般比較簡單。
事件發(fā)布之前需要先構建事件實體并持久化。事件發(fā)布的方式有很多種,你可以通過應用服務或者
領域服務發(fā)布到事件總線或者消息中間件,也可以從事件表中利用定時程序或數據庫日志捕獲技術
獲取增量事件數據,發(fā)布到消息中間件。
3.2 事件數據持久化
事件數據持久化可用于系統之間的數據對賬,或者實現發(fā)布方和訂閱方事件數據的審計。當遇到消
息中間件、訂閱方系統宕機或者網絡中斷,在問題解決后仍可繼續(xù)后續(xù)業(yè)務流轉,保證數據的一致
性。
事件數據持久化有兩種方案:
-
持久化到本地業(yè)務數據庫的事件表中,利用本地事務保證業(yè)務和事件數據的一致性。
-
持久化到共享的事件數據庫中。
需要注意的是:業(yè)務數據庫和事件數據庫不在一個數據庫中,它們的數據持久化操作會跨數據庫,
因此需要分布式事務機制來保證業(yè)務和事件數據的強一致性,結果就是會對系統性能造成一定的影
響。
3.3 事件總線 (EventBus)
事件總線是實現微服務內聚合之間領域事件的重要組件,它提供事件分發(fā)和接收等服務。
事件總線是進程內模型,它會在微服務內聚合之間遍歷訂閱者列表,采取同步或異步的模式傳遞數據。
事件分發(fā)流程大致如下:
-
如果是微服務內的訂閱者(其它聚合),則直接分發(fā)到指定訂閱者;
-
如果是微服務外的訂閱者,將事件數據保存到事件庫(表)并異步發(fā)送到消息中間件;
-
如果同時存在微服務內和外訂閱者,則先分發(fā)到內部訂閱者,將事件消息保存到事件庫(表),再異步發(fā)送到消息中間件。
3.4 消息中間件
跨微服務的領域事件大多會用到消息中間件,實現跨微服務的事件發(fā)布和訂閱。
消息中間件的產品非常成熟,市場上可選的技術也非常多,比如:Kafka,RabbitMQ等。
3.5 事件接收和處理
微服務訂閱方在應用層采用監(jiān)聽機制,接收消息隊列中的事件數據,完成事件數據的持久化后,就
可以開始進一步的業(yè)務處理。領域事件處理可在領域服務中實現。
4、案例
發(fā)生的領域事件是:繳費通知單已生成。下一步的業(yè)務操作是:繳費。
事件起點:出單員生成投保單,核保通過后,發(fā)起生成繳費通知單的操作。
-
投保微服務應用服務,調用聚合中的領域服務createPaymentNotice 和createPaymentNoticeEvent,分別創(chuàng)建繳費通知單、繳費通知單事件。其中繳費通知單事件類PaymentNoticeEvent繼承基類DomainEvent。
-
利用倉儲服務持久化繳費通知單相關的業(yè)務和事件數據。為了避免分布式事務,這些業(yè)務和事件數據都持久化。
-
到本地投保微服務數據庫中。
-
通過數據庫日志捕獲技術或者定時程序,從數據庫事件表中獲取事件增量數據,發(fā)布到消息中間件。這里說明:事件發(fā)布也可以通過應用服務或者領域服務完成發(fā)布。
-
收款微服務在應用層從消息中間件訂閱繳費通知單事件消息主題,監(jiān)聽并獲取事件數據后,應用服務調用領域層的領域服務將事件數據持久化到本地數據庫中。
-
收款微服務調用領域層的領域服務PayPremium,完成繳費。
-
事件結束。
提示:繳費完成后,后續(xù)流程的微服務還會產生很多新的領域事件,比如繳費已完成、保單已保存
等等。這些后續(xù)的事件處理基本上跟1~6的處理機制類似。
5、總結
今天我們主要學習領域事件以及領域事件的處理機制。
領域事件驅動是很成熟的技術,在很多分布式架構中得到了大量的使用。領域事件是DDD的一個
重要概念,在設計時我們要重點關注領域事件,用領域事件來驅動業(yè)務的流轉,盡量采用基于事件
的最終一致,降低微服務之間直接訪問的壓力,實現微服務之間的解耦,維護領域模型的獨立性和
數據一致性。
除此之外,領域事件驅動機制可以實現一個發(fā)布方N個訂閱方的模式,這在傳統的直接服務調用設文章來源:http://www.zghlxwxcb.cn/news/detail-836283.html
計中基本是不可能做到的。文章來源地址http://www.zghlxwxcb.cn/news/detail-836283.html
到了這里,關于05.領域驅動設計:掌握領域事件,解耦微服務的關鍵的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!