微服務架構是將複雜臃腫的單體應用進行細粒度的服務化拆分,每個拆分出來的服務各自獨立打包部署,並交由小團隊進行開發和運維,從而極大地提高了應用交付的效率。
從單體應用到微服務#
單體應用的困境#
早期互聯網公司的應用架構主要分為 LAMP(Linux + Apache + MySQL + PHP)和 MVC(Spring + iBatis/Hibernate + Tomcat)兩大流派。這些架構的優點是學習成本低、開發上手快,適合業務規模不大、團隊人員較少的階段。
然而隨著業務規模擴大,單體應用架構會面臨以下問題:
| 問題 | 描述 |
|---|---|
| 部署效率低下 | 程式碼越多、依賴資源越多,編譯打包部署一次可能需要 10 分鐘以上 |
| 團隊協作成本高 | 超過 5 人同時修改程式碼時,合併、測試、部署的協調成本極高 |
| 系統可用性差 | 所有功能部署在同一進程,一個模組出問題會影響整體服務 |
| 線上發布變慢 | 程式碼膨脹導致服務啟動時間變長,大規模機器發布耗時極長 |
一旦單體應用同時進行開發的人員超過 10 人,就會明顯遇到上述問題,這時應該考慮進行服務化拆分。
服務化的核心思想#
服務化就是把傳統單體應用中通過 JAR 包依賴產生的本地方法呼叫,改造成通過 RPC 接口產生的遠程方法呼叫。
以微博系統為例,原本內容模組、訊息模組、用戶模組的程式碼耦合在一起。通過服務化:
- 將用戶模組拆分成獨立服務,以 RPC 接口對外提供服務
- 其他模組通過遠程呼叫方式訪問用戶服務
- 用戶模組可以獨立開發、測試、上線和運維
微服務的定義與特徵#
Martin Fowler 的六大特徵#
Martin Fowler 於 2014 年將微服務定義為一種「架構風格」(Architecture Style),歸納出以下核心特點:
1. 一組小的服務 (A Suite of Small Services)
將單塊架構中的業務能力拆解為獨立的小服務。
關於「小」的定義標準
業界並無嚴格的程式碼行數規範。核心判斷標準在於認知負載:只要該服務的複雜度能讓單一開發人員完全理解並在腦海中構建出模型,即可視為足夠「微」的服務。
2. 獨立進程運行 (Running in its own Process)
每個微服務都在獨立的進程中運行,不共用進程空間。
- Java 應用部署在獨立的 Tomcat 容器中
- 現代化的 Docker 容器部署
- 透過進程級別的隔離,系統可以更靈活地進行橫向擴展
3. 輕量級通信機制 (Lightweight Mechanisms)
相較於傳統的重量級協議(如 SOAP),微服務傾向使用輕量級協議(主要是 HTTP RESTful API),減少訊息格式的負擔,確保服務之間的低耦合與通信效率。
4. 基於業務能力構建 (Built around Business Capabilities)
服務的劃分依據「業務領域」而非技術層次,例如:用戶服務、登入服務、商品服務,每個服務對應一個原子化的業務功能。
5. 獨立部署 (Independently Deployable)
每個服務由專屬團隊負責維護、開發與演進,團隊間無需大量協調即可自行決定部署時程,大幅提升系統迭代速度。
6. 去中心化管理 (Decentralized Control)
摒棄「統一技術棧、統一標準」的集中式管理模式:
- 技術多樣性:每個團隊可選擇最適合的技術棧
- 儲存多樣性:可針對不同服務採用不同的資料庫
Netflix 架構視角的定義#
前 Netflix 架構總監給出的定義:
“Loosely coupled service oriented architecture with bounded context.” (具有有界上下文的鬆散耦合服務導向架構)
這個定義涵蓋三個重要維度:
| 維度 | 說明 |
|---|---|
| 鬆散耦合 | 服務間依賴關係降至最低,開發時無需考慮周邊服務的存在 |
| 服務導向架構 | 微服務是 SOA 的更細化、更落地的實踐形式 |
| 有界上下文 | 每個團隊維護自己的資料源,拒絕使用集中式大型資料庫 |
微服務的利弊權衡#
架構師的職責在於權衡。微服務並非銀彈,在享受其帶來的敏捷與靈活性時,必須同時準備好應對分散式系統帶來的巨大複雜度。
三大優勢#
1. 強模組化邊界 (Strong Modular Boundaries)
在「服務」層級上實作模組化,其他團隊只需透過接口呼叫服務,無需共享 JAR 包或源程式碼。
2. 可獨立部署 (Independent Deployment)
團隊可獨立開發並部署服務,無需等待其他團隊,大幅減少協同成本。
3. 技術多樣性 (Technology Diversity)
每個團隊可根據業務特性選擇最優的技術堆疊。
技術多樣性雖然好,但並非越多越好。引入過多的技術堆疊會增加維護成本與人才招聘難度,需要適度把控。
四大挑戰#
1. 分散式複雜性 (Distributed Complexity)
單體架構可能只需一個團隊維護一個應用;微服務化後,系統可能分裂成數十甚至上百個服務,服務間透過網路溝通協作,理解系統運作機制的難度大幅上升。
2. 最終一致性 (Eventual Consistency)
不同團隊可能持有相同概念的資料副本,當一方修改了資料必須同步到其他相關方。
分散式系統極難保證強一致性,通常只能追求最終一致性。這是微服務架構中最棘手的挑戰之一,直接影響業務正確性。
3. 運維複雜性 (Operational Complexity)
服務間的依賴關係錯綜複雜,對系統監控、容量規劃、可靠性保障提出了極高的要求。
4. 測試複雜性 (Testing Complexity)
功能分散在各個服務中,端到端的整合測試需要多個團隊聯合協作,環境搭建與案例設計的複雜度呈指數級上升。
何時引入微服務#
複雜度與生產率的權衡模型#
建立一個二維座標系來分析:
- 橫座標:業務系統的複雜性(隨時間推移與功能增加而上升)
- 縱座標:研發團隊的生產率(交付效率)
單體應用曲線:初期生產率極高,但隨複雜度增加會顯著下降
微服務曲線:初期因基礎設施建設成本高導致生產率較低,但突破臨界點後能保持穩定高效產出
企業不應盲目追求微服務,而應尋找「交叉點」。根據經驗,當研發團隊規模接近 100 人 時,通常意味著業務複雜度已達到臨界值,此時應開始認真考慮向微服務架構轉型。
單塊優先原則 (Monolith First)#
推薦的演進路徑:
- 起步階段:所有功能打包在單塊應用中,快速開發並交付
- 發展階段:隨業務推進,架構師對業務領域的理解逐漸清晰
- 拆分階段:當單塊架構無法滿足需求時,識別需要獨立擴展的功能
- 演化階段:將特定模組剝離為獨立服務,逐步演化為微服務架構
為何不推薦「微服務優先」
- 領域邊界模糊:初期團隊對問題領域理解不深,難以準確劃分服務邊界
- 驗證風險:應用尚未經過市場驗證,若投入大量精力建置微服務架構卻遭遇商業失敗,將造成巨大的資源浪費
錯誤的拆分比不拆分更糟糕。
微服務架構的基本組件#
微服務架構下,服務呼叫主要依賴以下基本組件:
| 組件 | 職責 |
|---|---|
| 服務描述 | 定義服務接口名、參數、返回值等資訊 |
| 註冊中心 | 服務的發布與訂閱,服務地址的註冊與查詢 |
| 服務框架 | 解決通信協議、資料傳輸方式、資料序列化等問題 |
| 服務監控 | 監控服務呼叫的請求量、響應時間、成功率等指標 |
| 服務追蹤 | 記錄服務呼叫鏈路資訊,用於故障定位和問題追踪 |
| 服務治理 | 通過各種手段保證服務呼叫的成功率 |
這幾個基本組件共同組成了微服務架構,在生產環境下缺一不可。在引入微服務架構之前,團隊必須掌握這些基本組件的原理並具備相應的開發能力。
組織架構與康威法則#
康威法則 (Conway’s Law)#
設計系統的組織,其產生的設計等價於該組織的溝通結構。
如果組織架構是分散且隔閡的,系統架構往往也會變得支離破碎;反之,若要構建高效的微服務架構,必須先調整組織結構以適應之。
微服務組織的核心原則#
1. 全功能團隊 (Cross-functional Team)
每個微服務團隊內部應形成端到端的閉環:
- 團隊內包含產品專家、UX、研發、測試等所有必要角色
- 團隊長期圍繞該微服務進行持續開發與迭代
2. 兩個披薩原則 (Two-Pizza Rule)
單個微服務團隊的規模應控制在兩個披薩能讓所有成員吃飽的人數(約 10-12 人)。小規模團隊能確保溝通高效。
3. 誰開發,誰運維 (You build it, you run it)
開發者必須負責服務的構建、測試、發布、運行以及線上支援,這確保了團隊對程式碼品質有最高的敏感度。
Netflix 前總架構師曾言:「微服務架構本質上是一種組織架構的重組。」如果團隊依然受限於傳統的職能溝通壁壘,微服務的敏捷性無法真正實作。