一、領域事件
領域內的業務行為發生后通常會觸發進一步的業務操作,DDD中這類事件被稱為領域事件。比如電商領域,訂單下單后觸發支付動作,支付動作完成后觸發倉庫出貨動作,出貨完成觸發快遞運輸動作,這些都是業務流程中的步驟,以領域事件表示。
在和業務專家溝通的過程中,諸如一些他們聊到的關鍵詞“如果這樣,就那樣”,“這個完了就進行那個”,“發生xx得通知xxx”,類似這種關鍵詞時,則需要捕捉到這部分就是業務流程中的領域事件
二、DDD為什么需要領域事件驅動
領域事件發生后,以Spring似的的強依賴方式,引用下游事件進行處理,這樣會造成領域之間的強依賴。
領域事件驅動,可以切斷領域模型之間的強依賴關系,維護領域模型的獨立,實現領域模型的解耦,當領域模型映射到微服務實現時,則實現了微服務之間的解耦。這樣微服務之間不再需要分布式的強一致性事務,而是可以實現基於消息的數據最終一致性。
三、領域事件解耦微服務
領域事件解耦的關鍵點在於,事件發布方完成自己的業務邏輯后,發送通知下一個領域模型執行操作,這中間過程發布方可以不關心訂閱方的事件處理是否成功,實現領域間的解耦,這個領域可以是服務內聚合與聚合之間,也可以是多個微服務之間,數據的一致性也可以基於消息的最終一致性方案完成。

1、服務內實現事件驅動
(1)事件通知——觀察者模式
參考博客內對觀察者模式的講解:
https://www.cnblogs.com/jiyukai/p/14786534.html
(2)事件通知——Guava EventBus
Guava
EventBus允許在組件之間進行發布-訂閱式的通信,參考博客內對Guava EventBus的講解:
https://www.cnblogs.com/jiyukai/p/14828564.html
(3)數據一致性——服務內強一致性
在領域模型內,如果需要跨多個聚合實現業務邏輯時,要么通過事件總線實現微服務內的多聚合數據的最終一致性,要么通過事務機制保證數據的強一致性。
領域邏輯不涉及到事務回滾的:事件總線解決方案:
在采用事件總線進行領域事件處理時,可以根據需要完成領域事件實體的構建,然后發布方聚合會將領域事件發布到事件總線,訂閱方聚合接收領域事件后完成后續業務處理。事件總線的設計方式存在開發復雜度,需要結合實際情況具體分析
領域邏輯涉及事務回滾的:應用層采用事務機制保證數據的強一致性:
在應用層增加事務控制,在對多個聚合的領域服務進行組合和編排時,通過事務機制來確保多個聚合在提交數據時實現數據強一致性。這種方式應用於實時性和數據一致性要求高的場景。
2、服務間實現事件驅動
(1)事件通知——MQ
服務間涉及事務的事件驅動,可以采用分布式事務技術來保證服務間的數據強一致性,但分布式事務基於二階段提交的過程會嚴重影響系統性能,同時增加微服務之間的耦合。
微服務之間的領域事件可以采用異步化的最終一致性設計,基於消息中間件的事件驅動,實現微服務的解耦,推動業務流程在不同的子域或微服務之間進行流轉,減輕微服務同步訪問壓力的同時,也避免了很多情況下某個微服務宕機導致的雪崩效應。
參考博客內對最終一致性的講解:
https://www.cnblogs.com/jiyukai/p/9463626.html
3、領域事件驅動實現細節
- 事件實體的基本屬性應該包括事件唯一標識,發生時間,事件類型和事件源,記錄事件自身屬性和發生背景相關的數據。
- 事件實體還記錄了事件發生時相關的業務數據,業務數據隨着事件發布傳輸到訂閱方,由訂閱方開展下一步業務操作
- 事件發布前,要把事件實體持久化到數據庫事件表中(方便數據對賬,問題溯源,防止服務宕機導致事件丟失),事件的發布可以通過事件總線,消息中間件直接投遞或者采用定時輪詢數據庫日志捕獲技術(CDC),獲取增量事件數據,進行推送
- 事件發布在應用層實現,事件觸發的業務邏輯實現在領域層實現。
參考書籍 ——《基於DDD和微服務的中台架構與實現》歐創新、鄧頔
參考書籍 ——《領域驅動設計》Eric Evans
參考書籍 ——《架構真經》Martin L. Abbott