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