針對每一個微服務所擁有的資料庫發生變更時所産生的事件,要如何做出相對應的動作, 以維護其所擁有的資料庫或資料倉儲中的資料的時效性; 這确實不是件容易的事, 本文提供了四種架構方案。
架構師在設計從多個微服務取資料, 而生成報表的架構設計方案時, 往往面臨著需在邊界上下文 (Bounded Context), 資料的時效性, 性能, 可靠性與開發的複雜度間作取舍。
從多個微服務取資料, 而生成報表的設計方案, 主要是參考: Enterprise Integration Patterns; Hohpe and Woolf。
A. Database Pull Model (Shared DataIntegration Style):
直接至各微服務所擁有的資料庫中擷取資料, 并寫至負責生成報表的服務所擁有的資料庫或資料倉儲中。此設計方案主要的問題是: 破壞了原微服務的邊界上下文 (Bounded Context), 使得原微服務無法獨立自主的修改自身所擁有的資料表結構; 原微服務若有任何資料表結構上的修改, 将會影響到生成報表的服務所擁有的資料庫或資料倉儲。

圖一: Database Pull Model
B. Http Pull Model (RPC IntegrationStyle):
負責生成報表的服務, 經由各微服務所提供的 REST API, 取得所需的資料, 并寫至自身所擁有的資料庫或資料倉儲。此設計方案, 藉由 REST API, 維持了各微服務的邊界上下文 (Bounded Context), 但, 卻存在著其他的問題:
性能上的問題: 當負責生成報表的服務需同時向許多個 (上百個) 微服務擷取資料時, 則就表示将會有上百個遠端調用會發生。是以, 有可能負責生成報表的服務的某一個資料請求, 已經達到了 Time Out, 但有的微服務所提供的資料, 還尚未送至負責生成報表的服務。
資料量的問題: 當負責生成報表的服務向微服務擷取大量的資料時; 例如: 整個月的股票買賣。則大量的資料将造成大量流量, 是以, 也有可能對負責生成報表的服務的某一個資料請求, 造成 Time Out。
圖二: Http Pull Model
C. Batch Pull Upload (Shared DataIntegration Style):
在夜間執行批處理至各微服務所擁有的資料庫中擷取資料, 并寫至負責生成報表的服務所擁有的資料庫或資料倉儲中。
此設計方案因為同樣是屬于 Shared Data IntegrationStyle, 是以, 也存在著破壞了原微服務的邊界上下文 (Bounded Context) 的問題; 使得原微服務無法獨立自主的修改自身所擁有的資料表結構。原微服務若有任何資料表結構上的修改, 将會影響到生成報表的服務所擁有的資料庫或資料倉儲。
當然, 此設計方案的另一個問題便是: 資料的時效性; 生成報表的服務所擁有的資料庫或資料倉儲, 将無法獲得實時的各微服務所擁有的資料庫中的資料。
圖三: Batch Pull Upload
D. Event-Based Push Model (MessageBased Integration Style):
當各微服務所擁有的資料庫發生變更時, 便會産生一個事件。此事件便會使得生成報表的服務去處理此事件; 至發生資料庫變更的微服務擷取所變更的資料, 并寫入其所擁有的資料庫或資料倉儲中。
此設計方案不僅維持了各微服務的邊界上下文 (Bounded Context), 更使得生成報表的服務所擁有的資料庫或資料倉儲, 獲得實時的各微服務所擁有的資料庫中的資料; 擁有資料的時效性。
圖四: Event-Based Push Model
比較這四種設計方案在邊界上下文 (Bounded Context) 、資料的時效性上的優、劣:
邊界上下文
資料的時效性
Database Pull Model
劣
優
Http Pull Model
Batch Pull Upload
Event-Based Push Model
當然, 天下沒有白吃的午餐; Event-Based Push Model 雖然維持了邊界上下文 (Bounded Context) 并提供了資料的時效性。但, 卻增加了産品架構的複雜度。使得微服務與生成報表的服務間産生某種程度上的耦合。也就是說, 生成報表的服務必需知道: 針對每一個微服務所擁有的資料庫發生變更時所産生的事件,要如何做出相對應的動作, 以維護其所擁有的資料庫或資料倉儲中的資料的時效性; 這确實不是件容易的事。