分散式系統中的解耦模式:概要事件 - mathiasverraes

banq發表於2019-05-12

不要發出領域事件流,而是發出一個概要/摘要事件Summary Event。

問題

業務流程涉及許多步驟,每個步驟都會產生領域事件。事件的消費者依賴於這些事件中的資訊,並要偵聽所有這些事件以做出有意義的決定。當只有少數事件型別時工作很好,但是當事件型別的數量很多時,我們可以發現消費者需要對生產者業務流程進行了解,消費者現在幾乎就像一個微觀管理者,看著生產者的一舉一動,並立即報告生產者所做的一切。

這存在風險:當原始業務流程演變發展時,可能會新增,刪除或更改事件型別。就需要對消費者進行更改以適應新的事件型別,並且要麼同時部署,要麼具有良好的版本控制策略。

如果有多個消費者,所有人都需要了解生產者發出的每種型別的事件,情況會變得更糟。通常也會有一些重複:每個消費者都會根據事件投射相似或相同的狀態。

解決

原始業務流程可以將所有事件私下保留,而不是發出每個事件。在流程結束時,該流程會發出一個概要事件。此事件是冗餘的,因為它包含前面事件中已有的資訊。消費者現在只是收聽這個概要事件,而不是瞭解發出的每一個事件,這個事件告訴他們需要知道的一切,幾乎沒有與他們無關的資訊。消費者不需要在流程中跟蹤狀態變化,因為他們最終得到了所有變化,然後可以對它們採取行動。

通過檢查消費者,可以發現使用概要事件模式的機會:如果消費者監聽多種事件型別,但只有一種事件型別導致消費者做一些有意義的領域操作(除了保留狀態),這是一個好兆頭。生產者也提供線索:業務流程涉及建立某種人工製品,商業價值不一定在人工製品本身,而是在人工製品建立之後的使用。(Cyrille的@TODO Cfr Three Archetypes)

案例

許多業務流程涉及為以後的生產用途建立一個人工製品:在一個訂購流程中,不同的使用者可能會新增和刪除他們希望訂購的專案的一行行條目,他們可能會改變他們想要的物品數量。客戶經理可能會根據可用庫存更改數量更改價格等等。

在最初的設計中,消費者監聽:LineItemWasAdded,LineItemWasRemoved,QuantityWasChanged,PriceWasChanged,以及ShippingAddressWasAdded等事件;消費者(比如OrderFulfilment流程)會監聽大多數這些事件,並預測需要打包和發運的專案列表。

但流程處理OrderFulfilmentProcess在事件OrderWasPlaced到來之前什麼都不做,直到收到這個事件,表示是它開始行動的時候了。在OrderWasPlaced事件沒有冗餘資訊,所以它主要是有OrderId,別的都不需要。

我們現在可以重構這個訂購流程,以保持其所有事件的私密性。我們製作一個公共事件OrderWasPlaced,但是這個事件包含有關訂單的完整資訊。實際上,OrderWasPlaced是實際訂單的文件。(@TODO我相信這是企業整合模式中的文件訊息模式)。

在訂單下游部門工作的人通常不瞭解訂單作為草案指定中發生的細節變更,他們只接受包含結果訂單的訊息,然後採取行動。

弱點:

  1. 有時,消費者確實需要了解生產者的許多內部細節才能完成其工作。在這種情況下,概要事件模式沒有用,因為它不僅包含結果資訊,還包含有關流程中每個步驟的後設資料。
  2. 在上面的訂購示例中,OrderFulfilment不關心訂單的價格。比方說RevenueReporting,另一個消費者關心的是價格而不是訂購的確切商品。然而,他們都收到了同樣的OrderWasPlaced事件。可能存在一個問題例如,其中某些資訊是敏感的,只應該暴露給一方。另外一方隱瞞。
  3. 新增了另一種事件型別Summary Event,即“替換所有標準的新標準”。
  4. 這Summary Event可能不屬於生產者的領域。在這種情況下,我們可以新增一箇中間服務,它消耗生產者的事件,彙總它們,然後發出Summary Event消費者。

 

相關文章