概述#
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 type | Domain |
| Number of quanta | 1 to many |
| Deployability | 4/5 |
| Elasticity | 5/5 |
| Evolutionary | 5/5 |
| Fault tolerance | 4/5 |
| Modularity | 5/5 |
| Overall cost | 1/5 |
| Performance | 2/5 |
| Reliability | 4/5 |
| Scalability | 5/5 |
| Simplicity | 1/5 |
| Testability | 4/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 量測所評估的特性。
極致解耦的驅動哲學在這個架構中創造了許多挑戰,但做得好時會帶來巨大的收益。如同任何架構,架構師必須理解規則,才能聰明地打破它們。