天天看點

基于領域事件實作微服務解耦

基于領域事件實作微服務解耦

領域事件是解耦微服務的關鍵。

什麼是領域事件

除了指令和操作等業務行為,還有一種非常重要的事件,這種事件通常會導緻進一步的業務操作,在DDD(Domain Driven Design,領域驅動設計)中,這種事件叫做 領域事件。

領域事件可以是業務流程中的一個步驟。比如,投保業務繳費之後,投保單轉為保單。支付成功後,生産商品訂單。這裡的支付就是一個領域事件。或者是一個事件發生後觸發進一步操作, 比如,密碼連續輸入錯誤3次,賬戶鎖定。這裡的密碼輸入就是一個領域事件。

如何識别領域事件

使用者旅程或者場景分析時,捕捉業務/需求人員或者領域專家口中的關鍵詞:

  • 如果發生 。。。。,則。。。
  • 完。。。。的時候,請通知。。。
  • 發生。。。。時,則。。。

微服務之間的領域事件

跨微服務的領域事件會在不同界限上下文或領域模型直接實作業務協助,主要目的是實作微服務解耦。減輕微服務直接實作服務通路的壓力。

舉個例子:

當使用者在購物車點選結算時,生成待付款訂單,若支付成功,則更新訂單狀态為已支付,扣減庫存,并推送撿貨通知資訊到撿貨中心。

在你沒有接觸領域事件或EDA(事件驅動架構)之前,你會如何實作這個用例?肯定是簡單直接的方法調用,在一個事務中分别去調用狀态更新方法、扣減庫存方法、發送撿貨通知方法。

上面的實作有什麼問題?

  • 試想一下,若現在要求支付成功後,需要額外發送一條付款成功通知到微信公衆号,我們怎麼實作?想必我們需要額外定義發送微信通知的接口并封裝參數,然後再添加對方法的調用。這種做法雖然可以解決需求的變更,但很顯然不夠靈活耦合性強,也違反了OCP。
  • 将多個操作放在同一個事務中,使用事務一緻性可以保證多個操作要麼全部成功要麼全部失敗。在一個事務中處理多個操作,若其中一個操作失敗,則全部失敗。但是,這在業務上是不允許的。客戶成功支付了,卻發現訂單依舊為待付款,這會導緻糾紛的。
  • 違反了聚合的一大原則:在一個事務中,隻對一個聚合進行修改。在這個用例中,很明顯我們在一個事務中對訂單聚合和庫存聚合進行了修改。

如果基于領域事件如何實作?

領域事件模組化

  1. 事件源    entry
  2. 事件對象 domainMessage  = 事件類型 eventTopic + 事件源  entry
  3. 事件監聽器   subscribe 處理事件
  4. 事件分發器 注冊監聽器  JvmEventConsumer
  5. 生産消息 實時消費,producer中直接consume 或者 MQ的形式,異步消費
基于領域事件實作微服務解耦

領域事件 = 事件釋出 + 事件存儲 + 事件分發 + 事件處理。

為啥基于領域事件驅動的設計能夠實作系統解耦?

關鍵是因為居于事件驅動架構 【Event-Driven Architecture(事件驅動架構))】

事件驅動架構有三個特性:

  1. 異步
  2. 實時
  3. 徹底解耦

EDA 架構的核心是基于消息的釋出訂閱模式,通過釋出訂閱,消息消費方對于消息發送方而言是完全透明的,發送方隻是把消息正常發送到消息中間件,其他的不關心, 及時發送消息的時候,消息接收方不可用,消息生産者仍然可以發送消息,這樣實作了系統間的徹底解耦,不存在系統間的依賴。

總結

領域事件是 DDD 的重要概念,設計時需要關注領域事件,用領域事件來驅動業務流轉,盡量采用事件的最終一緻性,降低微服務直接的耦合,實作微服務間的解耦,維護領域模型的獨立性和資料一緻性。

參考資料:

  • ​​https://liqiang.io/post/ddd-practice-part-02-architecture-ac314d3d​​
歡迎關注公衆号:程式員開發者社群

繼續閱讀