使用Apache Kafka實現從單體到事件驅動微服務 - swlh

banq發表於2021-12-17

我們將設計一個基於經典遺留應用程式的進化事件驅動系統,類似於在世界各地的許多組織中可以找到的系統。這個練習將向我們展示事件驅動架構的潛力。
 

訊息驅動與事件驅動區別
讓我們考慮兩個需要透過訊號相互傳遞資訊的鬆散耦合元件。在這兩種正規化中,元件非同步傳遞訊號,允許它們在不等待響應的情況下傳輸資訊。細微的區別在於傳送這些訊號背後的意圖,以及它們的最終目的地:

  • 事件是向事件儲存區提出的簡單通知
  • 訊息 是傳送給可定址接收者的資料

訊息背後的意圖是向某人傳達某些資訊。對於事件,它只是為了交流一些東西。就是這樣!
訊息的接收者會隨著時間的推移而改變。事件的目的地始終保持不變——它是事件儲存。
這就是強大的事件驅動方法如何實現真正的松耦合。
(banq注:訊息是上下文敏感的,和上下文有關,一個訊息就像一條河裡的一朵浪花,說明不了什麼;而一則事件則可以說明問題,更強調行為動作,上下文變成隱式背景了。)
 
分散式事件驅動系統中發生的所有互動都濃縮為三種型別:
  • 事件:對系統某些事實的觀察。是否會觸發副作用。
  • 命令:必須使系統做某事的事件。必須觸發副作用。
  • 查詢:檢視系統內部狀態的請求。一定不會引發副作用。

副作用會改變系統的內部狀態——更新資料庫、強制業務流程執行等。
我們很少期望透過檢視資料庫中的資料來更改系統中的某些內容,因為這樣的操作沒有副作用。

進化的單體
這是我們的患者:一個名為CRUX的單體應用程式。它是緊耦合遺留應用程式的經典示例。
它有一些 RESTful API,以及一個 Apache Kafka 的整合例項,可以將一些事件資料推送到 AWS S3。
我們會將其轉變為成熟的、事件驅動的微服務架構。
 

  • 進化第一步:解耦微服務

1.釋放查詢
首先,我們將簡單地在已經開發和執行的 API 上使用Event-Carried State Transfer 模式,以提高它們的讀取速度並做一些初始準備工作。
部署在CRUX旁邊的 Redis 資料庫的各個狀態將使用Apache Kafka 例項傳輸到服務的本地狀態儲存,從現在開始稱為事件儲存。
現在透過快速且廉價的本地資料查詢來提供查詢服務。其他一切仍然透過CRUX執行。微服務的狀態透過 Event Store 的 State Transfer不斷更新。
在這個階段的早期,我們應該對來自CRUX 的事件應用事件溯源到狀態重播的微服務。開發需要一段時間,但事件溯源是一個強大的工具,可以讓您在路上掌握事件。這很值得!
在實踐中,Confluent 提供了各種聯結器應用程式,可以幫助您相當輕鬆地將 Event Store 與服務資料庫連線起來。

2. 釋出命令
接下來,需要棄用傳統的 WRITE 通道。我們希望我們的微服務能夠控制它們的狀態——我們可以透過Notification Events來實現。
微服務應該生成關於它們向事件儲存的狀態更改的通知,再次觸發狀態傳輸並更新它們的狀態儲存以及CRUX Legacy 資料庫。
這裡誕生了我們的第一個事件驅動的微服務:)
在檢視微服務狀態時,我們傳送一個 Query,並接收返回的檢視。當改變那個狀態時,我們傳送一個描述狀態改變的命令,然後立即應用到微服務資料庫。這種模式稱為命令查詢職責分離
狀態更改仍在傳輸回CRUX。資料不再歸單體所有,但依賴於它的剩餘功能仍然滿足。
這就是我們看到最終一致性在起作用的地方——我們希望在更新事件之後,微服務的狀態最終將與 CRUX 中的狀態相等,將所有內容保持在一起。總的來說,這是對事件驅動架構的主要批評,出於某種原因,這讓人們非常不舒服。根據我的經驗,以及與我交談過的其他人,您很少需要嚴格一致性,因此這只是將可能發生的事情作為現實的一部分來接受的問題。但我們暫時不要專注於此。
  • 進化第二步驟:扼殺單體


駐留在 CRUX 中的功能應該按照Strangler 模式逐步轉移到各自的事件驅動微服務中。
我們可以使用事件協作模式來設計跨越多個服務生成不同型別事件的工作流。
我們還可以包含指向由其他事件觸發的事件的指標,允許定位先前處理的事件。
在協作微服務覆蓋了所有功能之後,CRUX 可以作為故障轉移機制保持執行(以防我們的一個新微服務失效)或完全棄用。
 
  • 進化第三步驟:上下文化微服務

微服務需要放入各自的Bounded Contexts有界上下文,然後拆分為 Query 和 Command 端元件。
在每個上下文中,都應該有一個系統事件儲存,只能由其中的服務訪問。它應該包含上下文中的協作成功所需的上下文微服務生成的所有事件。每當發生需要更新域特定狀態的里程碑事件時,應生成域事件並將其傳送到域事件儲存。
此類事件對領域專家意義重大。這是將我們的應用程式狀態保持在一起的資料,使系統最終跨上下文保持一致。領域事件應該比系統事件更重要,並且它們的架構很少改變。
 

應用事件驅動進化的好處

  • 新架構的元件鬆散耦合且位置透明。
  • 域和系統事件的分離將不需要的資料耦合的風險降至最低。這種劃分對於識別業務領域所需的核心資料耦合很重要。
  • 由此產生的可插拔架構專為變化而設計,使軟體開發人員能夠專注於在不斷變化的敏捷環境中快速提供業務功能。
  • 引入新的微服務和上下文沒有副作用,並且不會中斷系統中任何其他元件的工作。
  • 得益於CQRS模式,用於寫入和讀取的分離元件可以獨立最佳化和擴充套件,最大限度地減少資源使用並在重負載下保持良好的響應能力。
  • 事件溯源提供完整的系統審計,提高系統透明度並提供收集客戶行為洞察的方法。系統配備了所有歷史變化的不可變日誌,為進一步處理提供歷史資料。
  • 最後,微服務之間的關注點的明確分離導致更簡單的依賴樹、更直觀和易於理解的程式碼庫,從而加快編碼和專案交付時間。
  • 由於元件的隔離,解耦架構提供了為給定要求選擇更合適的技術的可能性。
  • 上下文具有明確的邊界和職責,這使得組織的可擴充套件性和工作分工更加精簡。


 

相關文章