概述#

Microservices(微服務)是近年來獲得巨大動力的架構風格。本章概述了使這個架構在拓撲和哲學上與眾不同的重要特性。

歷史與演進#

大多數架構風格是架構師事後注意到反覆出現的模式而命名的。Microservices 不同——它在早期就被 Martin Fowler 和 James Lewis 於 2014 年 3 月發表的知名部落格文章 “Microservices” 中命名並推廣。

Microservices 深受 Domain-Driven Design (DDD) 的啟發,特別是其中的 bounded context(限界上下文)概念:

  • Bounded context 代表一種解耦風格
  • 在 bounded context 內部,程式碼和資料 schema 等內部組件相互耦合以完成工作
  • 絕不與 bounded context 外部的任何東西耦合
  • 每個 context 只定義自己所需的內容,而非遷就其他組件

如果架構師的目標是高度解耦,那麼他們會偏好重複而非重用(favor duplication over reuse)。Microservices 的主要目標就是高度解耦,物理實現 bounded context 的邏輯概念。

拓撲結構(Topology)#

Microservices 的拓撲包含:

  • API Layer(可選)——位於消費者與服務之間
  • 多個獨立服務——每個服務包含自己的模組和功能
  • 每個服務擁有自己的資料庫——實現資料隔離

由於其單一用途的特性,microservices 中的服務大小比其他分散式架構(如 orchestration-driven SOA)小得多。架構師期望每個服務都包含所有獨立運作所需的部分,包括資料庫和其他依賴組件。

Figure 17.1: The topology of the microservices architecture style

分散式與細粒度#

Microservices 構成一個 distributed architecture:每個服務在自己的 process 中運行,最初代表一台實體電腦,但很快演化為虛擬機器和容器。

  • 將服務解耦到這種程度,解決了共享基礎設施中的資源競爭與隔離不當問題
  • 透過雲端資源和容器技術,團隊可以在 domain 和 operational 層級都享受極致解耦的好處
  • Performance 是負面副作用:網路呼叫比方法呼叫慢得多,且每個端點的安全驗證增加額外處理時間

由於 microservices 是分散式架構,有經驗的架構師建議避免跨服務邊界的事務,使服務粒度的決定成為這個架構成功的關鍵。

Bounded Context(限界上下文)#

Microservices 的驅動哲學是 bounded context:每個服務模型化一個 domain 或 workflow。

  • 每個服務包含在應用程式中運作所需的一切:classes、subcomponents、database schemas
  • 在 monolith 中,開發者常共享通用類別(如 Address),但 microservices 偏好重複而非耦合
  • 每個服務代表一個 domain 或 subdomain——是 DDD 邏輯概念的物理體現

Data Isolation(資料隔離)#

Bounded context 驅動的另一個需求是資料隔離

  • 許多其他架構風格使用單一資料庫,但 microservices 盡量避免所有耦合
  • 架構師必須小心 entity trap——不要簡單地將服務模型化為資料庫中的單一實體
  • 由於不再有單一事實來源(single source of truth),架構師必須決定如何處理資料分散的問題
  • 好處:每個服務可以選擇最適合的資料儲存工具,團隊可以在不影響其他團隊的情況下更換資料庫

API Layer#

大多數 microservices 的圖示都包含一個 API layer,位於消費者與服務之間:

  • 它是可選的,但提供了有用的功能
  • 可作為 proxy 或連結到 naming service 等運營設施
  • 不應該被用作 mediator 或 orchestration 工具
  • 所有有趣的邏輯都應該發生在 bounded context 內部

API layer 不應包含 orchestration 或業務邏輯。這體現了 domain partitioning 與 technical partitioning 的區別:技術分割架構通常使用 mediator,而 microservices 堅定地採用 domain partitioning。

Operational Reuse(運營重用)#

Microservices 偏好重複而非耦合,但如何處理真正受益於耦合的運營關注點(如 monitoring、logging、circuit breakers)?

Sidecar Pattern#

  • 每個服務中的通用運營關注點作為獨立的 sidecar component 出現
  • 可由個別團隊或共享基礎設施團隊擁有
  • 當需要升級監控工具時,只需更新 sidecar,所有 microservices 都會獲得新功能

Service Mesh#

  • 當每個服務都包含通用的 sidecar 後,可以建構 service mesh
  • 各 sidecar 連接到 service plane,形成跨所有 microservices 的一致運營介面
  • Service mesh 形成一個控制台,允許開發者整體存取服務的運營面向

Figure 17.4: The service mesh forms a holistic view of the operational aspect of microservices

Service Discovery#

  • 架構師使用 service discovery 來建構 microservices 架構中的彈性
  • 請求不是直接調用服務,而是通過 service discovery 工具,可以監控請求數量和頻率
  • 可自動啟動新的服務實例來處理 scale 或 elasticity 需求

Frontends(前端)#

Microservices 偏好解耦,理想上也應涵蓋使用者介面。兩種常見的前端模式:

Monolithic User Interface#

  • 單一使用者介面通過 API layer 呼叫後端服務
  • 可以是桌面、行動或 Web 應用

Figure 17.5: Microservices architecture with a monolithic user interface

Microfrontends#

  • 在使用者介面層級使用組件化方式,建立與後端服務同步的粒度和隔離
  • 每個服務發出對應的 UI component,前端與其他 UI component 協調
  • 團隊可以從 UI 到後端服務完整隔離服務邊界,將整個 domain 統一在單一團隊中

Figure 17.6: Microfrontend pattern in microservices

Communication(通訊)#

架構師必須在 synchronous(同步)與 asynchronous(非同步)通訊之間做出決定。Microservices 通常使用 protocol-aware heterogeneous interoperability

  • Protocol-aware:每個服務必須知道(或發現)使用哪種協定來呼叫其他服務
  • Heterogeneous:每個服務可能用不同的技術棧撰寫,完全支持多語言環境
  • Interoperability:服務透過網路呼叫彼此以協作和傳遞資訊

Choreography(編舞)vs Orchestration(編排)#

Choreography 使用與 broker event-driven architecture 相同的通訊風格:

  • 沒有中央協調者,尊重 bounded context 哲學
  • 每個服務根據需要呼叫其他服務
  • 例如:CustomerWishList 服務呼叫 CustomerDemographics 服務獲取缺少的資訊
  • 在複雜工作流程中,可能出現 front controller pattern——第一個被呼叫的服務同時擔任 mediator 角色

Figure 17.7: Using choreography in microservices to manage coordination

Orchestration 使用 mediator 模式:

  • 建立一個專門的 mediator 服務來處理業務工作流程的協調
  • 例如:PlaceOrder 服務作為 workflow owner,協調 OrderPlacement、Payment、Inventory 等服務
  • 雖然建立耦合,但將協調集中在單一服務中,使其他服務受影響較小

Figure 17.8: Using orchestration in microservices

兩種方案都不完美——軟體架構第一定律。Choreography 保持高度解耦但錯誤處理更複雜;Orchestration 引入耦合但簡化協調。

Figure 17.9: Using choreography for a complex business process

Figure 17.10: Using orchestration for a complex business process

Transactions 與 Sagas#

  • 跨 microservices 的事務違反了核心解耦原則
  • 最佳建議:不要在 microservices 中做跨服務事務——修正粒度!
  • 需要事務串連的設計通常表示服務粒度過細
  • 當不得已時,可使用 saga pattern:一個 mediator 服務協調跨多個服務的事務,並使用 compensating transaction framework(補償事務框架)處理錯誤

Figure 17.11: The saga pattern in microservices architecture

少量跨服務的事務有時是必要的;但如果它成為架構的主要特徵,那就犯了設計錯誤。

架構特性評分#

架構特性評分
Partitioning typeDomain
Number of quanta1 to many
Deployability4/5
Elasticity5/5
Evolutionary5/5
Fault tolerance4/5
Modularity5/5
Overall cost1/5
Performance2/5
Reliability4/5
Scalability5/5
Simplicity1/5
Testability4/5

關鍵觀察:

  • 高分項目:scalability(5)、elasticity(5)、evolutionary(5)、modularity(5)——這些是這個架構最強大的特性
  • 現代工程實踐支持良好:deployability(4)、testability(4)——microservices 無法離開 DevOps 革命和自動化運營的發展
  • Performance 較低(2):分散式架構必須進行大量網路呼叫,且每個端點需要安全驗證。許多效能優化模式存在,包括智慧資料快取和複製
  • Cost 和 simplicity 最低(1):這是一個極其複雜且昂貴的架構風格
  • Fault tolerance 良好(4):獨立的單一用途服務通常具有高容錯性,透過 redundancy 和 service discovery 可進一步改善

Figure 17.13: Ratings for microservices

何時使用#

Microservices 是一個堅定的 domain-centered architecture(以領域為中心的架構),每個服務邊界應對應到 domain。它也擁有所有現代架構中最多的獨立 quanta——在很多方面,它體現了 quantum 量測所評估的特性。

極致解耦的驅動哲學在這個架構中創造了許多挑戰,但做得好時會帶來巨大的收益。如同任何架構,架構師必須理解規則,才能聰明地打破它們。