本章概覽#
第 6 章說明巨石架構在許多情境下是合適選擇,但當業務關鍵應用真的變得龐大,應用與其開發組織就會超過巨石的承載能力——五個流暢交付品質屬性(可修改性、可測試性、可部署性、可觀測性、可演化性)再也滿足不了。這時,遷移到微服務架構才有意義。
第 1 章已給出微服務架構的定義並說明它如何促進流暢交付。本章在那個基礎上深入展開:
- 結合第 3 章(架構基礎)與第 4 章(四種耦合)的概念,重新檢視微服務架構的定義。
- 探討微服務如何支援第 5 章的五個流暢交付品質屬性。
- 更深入分析微服務的缺點與採用挑戰。
- 介紹微服務架構模式語言(microservice architecture pattern language)。
本章將討論的主題#
- 微服務架構為何能在大規模情境下促成流暢交付
- 微服務架構的缺點
- 微服務架構模式語言概覽
微服務架構是什麼#
微服務架構是一種架構風格,把應用的子領域組織成兩個或更多的元件(亦稱「服務」),這些元件獨立可部署且鬆耦合。
這個定義包含五個關鍵概念:
- 它是一種架構風格(architectural style)。
- 應用由兩個或以上的服務組成,每個服務都是一個元件(可部署單元)。
- 服務由子領域組成。
- 服務鬆耦合。
- 服務可獨立部署。

Figure 7.1: A simple microservice architecture with three services (Order, Delivery, Consumer) plus an API Gateway
與其他常見定義對比#
Martin Fowler 與 James Lewis 的經典定義:
「微服務風格是把單一應用開發為一群小服務的方式,每個服務在自己的 process 中運行,以輕量機制(常為 HTTP RESTful API)互相溝通。這些服務圍繞**業務能力(business capabilities)**建構,由全自動部署機制獨立部署;最低限度的中央管理,服務可使用不同程式語言與不同資料儲存技術。」
Adrian Cockcroft 較簡潔的版本:「鬆耦合的服務導向架構,具備有界上下文(bounded contexts)。」
與 Fowler 定義的相同之處#
- 圍繞業務概念組織(Fowler 用「business capabilities」,作者用「subdomains」,可由 business capabilities 推導,第 20 章詳述)。
- 獨立可部署。
- 自動化部署(作者定義雖未明說,但第 5 章說明流暢交付要求自動化部署管線)。
- 多技術棧(作者定義雖未明說,但「服務即元件」隱含了這一點)。
與 Fowler 定義的差異#
- 大小:作者刻意不提服務的大小——「micro」字面化會誤導組織做出過度細粒度架構。目標是滿足品質屬性,不是讓服務變小。
- 可替換性(Replaceability):作者不視「拋棄重寫」為微服務的重要目標,尤其在它需要一堆小服務時。即便元件只有一個技術棧,只要保留 API,內部子領域或更小的元素仍是可替換的。
- 通訊技術:作者不指定特定 IPC 技術——REST、messaging 等各有取捨(第 3 章詳述)。
- 鬆耦合:作者把鬆耦合明確列為定義特徵之一。第 4 章已說明它的核心地位,7.3.2 會解釋它在微服務裡為何特別關鍵。
微服務架構不只是「服務」#
定義只觸及到元件視角。微服務架構至少還有三個重要面向:
- 系統操作:存在於服務之間的「空隙」——跨服務的分散式操作遠比本地操作複雜,會反過來限制子領域如何被切分到服務。
- 建置架構維度:獨立部署的需求會塑造程式碼倉、建置專案、部署管線。
- 服務與團隊的關係:適切的對應關係是流暢交付的關鍵。
服務的結構#
- 服務由一或多個子領域組成。
- 服務有 API(operations + events)。
- 服務可能消費其他服務的 API。
- 服務通常有自己的資料庫——但是私有實作細節,藏在服務 API 後面。
範例:Order Service 包含 Order Management 與 Money 兩個子領域;前者只在 Order Service,後者是被多個服務共用的 library。

Figure 7.2: A service consists of one or more subdomains, has an API of operations and events, may collaborate with other services
API 內容:
- 部分操作對應系統操作(
Order Service.createOrder()對應createOrder()系統操作)。 - 部分操作純粹是服務間協作用(
Consumer Service.reserveCredit()被Order Service.createOrder()呼叫)。
系統操作的兩種類型#
- 本地操作(local):單一服務完整處理。例:
createConsumer()。 - 分散式操作(distributed):跨多個服務。有「進入點」服務,該服務再與其他服務協作完成請求。例:
createOrder()。
分散式操作幾乎永遠比本地操作複雜得多——後續 7.5.1 會深入分析原因。

Figure 7.3: Two types of system operations — local (single service) and distributed (span multiple services)
建置架構#
兩種主要做法:
- multi-repo:每個服務一個程式碼倉、一個建置專案、一個部署管線。各自獨立測試與部署,擴張容易;全域變更(例如依賴升級)需跨多個 repo 協調,較難。
- monorepo:所有服務放在單一 repo。全域變更最容易;但要做到真正獨立部署很有挑戰,大型 monorepo 還需要在 build system 上大量投資,容易喧賓奪主。

Figure 7.4: Multi-repo build architecture — each service has its own deployment pipeline
服務 ⇔ 團隊的關係#
理想狀況:每個服務由單一團隊擁有——服務間鬆設計期耦合,團隊就能獨立開發、測試、部署。
但「服務 = 團隊」並非嚴格 1:1。一個服務可能包含多個子領域、多個團隊擁有(例如 Consumer Service 同時包含由 Consumer Management team 擁有的 Consumer Management 子領域,以及由 Order Management team 擁有的 Money 共用 library)。有時即使犧牲一些團隊自主性,也得把兩個非函式庫子領域併進同一個服務——例如網路通訊成本過高無法接受(第 20 章詳述)。
微服務架構的兩個必要特徵#
必要特徵 #1:服務可獨立部署#
「獨立可部署」有三個層面:
- 服務必須是元件(component):可執行 JAR、OS 執行檔、container image、Lambda zip 等;不是要打包進其他元件的 library。
- 服務必須有自己的部署管線:沒有獨立管線就無法獨立部署——必須跟別的服務一起部署、與其他團隊協調,自主性大打折扣。
- 服務在被獨立測試後即生產 ready:管線跑出的服務即可上生產,不需要其他服務一起測試;Client 與 collaborator 用 test double 模擬。

Figure 7.5: A service must be independently deployable — packaged, has its own pipeline, production-ready after isolated testing
隔離測試的兩個關鍵:
- 刻意設計簡單、明確、穩定的 API,讓 client 與 collaborator 易於模擬。
- 用 consumer-driven contract test(消費者驅動契約測試,第 15、16 章詳述)驗證雙方對 API 的共識——契約破損就 fail,不需要把服務一起跑。
為什麼有人放棄 contract test?#
Chris Richardson 觀察到的故事:某組織說 contract test「太麻煩」,改回應用層級端到端測試。
真正的根因往往是:過度細粒度且設計期緊耦合的架構,讓 contract 又多又不穩——這是「More the Merrier」反模式的副作用,而不是 contract test 本身的問題。
獨立部署的兩大好處#
- 加速、簡化、提升管線可靠性:擺脫慢、複雜、容易隨機失敗的端到端測試。例:測 Order Service 不用先把 Consumer Service 拉起、建立 Consumer 再建立 Order;只測 Order Service,Consumer Service 用 test double 模擬。
- 減少跨團隊協調:測試耦合會讓一團隊的失敗阻擋另一團隊的釋出;獨立部署讓團隊真正各自快速且安全地發布。
必要特徵 #2:服務鬆耦合#
四種耦合在微服務情境下的含義:
設計期耦合:必須鬆#
服務間設計期緊耦合會帶來高昂的「同步變更」(lock step change)成本——特別跨團隊時。例:Consumer Service 的 API 要做破壞性變更時,Consumer Management team 必須:
- 在現有 API 旁加上新版 API。
- 等所有 client team 把服務遷移到新版。
- 全部遷移後才能刪掉舊版。
破壞性 API 變更是微服務的內在風險之一——所以鬆設計期耦合是必備。
執行期耦合:應該盡量鬆#
不至於阻擋流暢交付,但會增加延遲、降低可用性。設計時必須在「服務切分」與「執行期耦合」之間做取捨——必要時把多個子領域合併到同一服務中(第 20 章詳述)。
建置期耦合:通常不是問題#
服務各自獨立建置,服務間不會有建置期耦合;服務內部可能有,但程式碼庫小,管線通常還是快;真有需要可套用第 6 章的物理設計原則。
基礎建設耦合:多半是選擇問題#
取決於部署架構——例如是否共用資料庫伺服器,是「共享便利」與「耦合風險」的取捨。
微服務的好處#
最大的好處是支援流暢交付;此外還有:
支援流暢交付(滿足五大品質屬性)#
- 高可修改性:服務間鬆設計期耦合,單一服務變更鮮少波及其他服務,團隊高度自主——但需要紀律,持續管理服務間依賴。
- 高可演化性:多元件架構,技術棧可漸進式升級,一次升一個服務;每個服務還能用最適合自己的技術棧。
- 高可測試性:服務小且能隔離測試,不需慢且脆弱的端到端測試;每個服務的部署管線只處理少量變更,難變成瓶頸;難測的功能可隔離到自己的服務,不影響其他服務的可測試性。
- 高可部署性:服務小、獨立部署,部署快且可靠;團隊可不用協調(甚至並行)部署;管線難變瓶頸。
- 高可觀測性:每個服務各自吐 telemetry,比巨石細緻——若一個服務只裝一個子領域,就能直接得到該子領域層級的觀測資料。
支援多技術棧#
「right tool for the right job」。不過為避免無政府狀態,組織仍要主動管理「核可技術」清單。
試新技術也更容易、更安全:做一個服務、上線、評估;成功代表組織驗證了一個新棧,失敗也只丟掉一個服務的工。
讓組織能擴張#
《Wiring the Winning Organization》(Gene Kim、Steven J. Spear,2023)記錄 Amazon 在 2002 年因為單一巨石而交付速度大幅下降;後來轉為微服務架構(書中稱為「modularization」),到 2025 年據稱每天部署 13 萬次。
新團隊可接手新服務,協調成本極低;每個服務各有部署管線,build 架構隨組織擴張。
改善開發者體驗#
開發者多數時間在自己的小程式碼庫工作,認知負荷低、回饋快、團隊小且獨立;與其他團隊偶爾協作以實作分散式操作。心流(flow)更好,生產力更高。

Figure 7.6: From a service developer's perspective, their world is far simpler than working on a monolith
依特徵切分子領域#
子領域常有不同特徵:
- 資源需求:Order Management 用一般機器,Fraud Detection 需要 GPU(p4d.24xlarge 是 m5.24xlarge 的 8 倍價格);分服務後可獨立 scale,大幅降低成本。

Figure 7.7: Subdomains within the same service are scaled together; separate services enable independent scaling
- 特定領域法規:醫療軟體要符合 ISO 13485、ISO/IEC 62304,與 DevOps 風格相衝;把受規範子領域隔離成獨立服務,其他可繼續用 DevOps。
- 業務關鍵性 → 可用性:把關鍵子領域(例如信用卡授權)隔離,避免被低關鍵子領域(例如 Merchant Account 管理)拖垮。
- 安全性:把處理 PII 等敏感資料的子領域隔離成服務,API 成為安全邊界,可加上防火牆、service mesh 規則、私有子網等網路控制,降低攻擊面。
- DDD 子領域類型:Core(核心競爭力,自己寫)、Supporting(常見但需客製,可外購但常自己寫)、Generic(常見且不需客製,直接外購);把 core 隔離成服務以加速核心競爭力的迭代。
微服務的缺點#
分散式操作很複雜#
服務同時是行程邊界與交易邊界,設計分散式操作時要面對:

Figure 7.8: Services are process and transaction boundaries, so distributed operations are far more complicated than local operations
- 網路通訊的成本與延遲:方法呼叫是奈秒級,網路通訊是毫秒級,頻寬有限;但真正的問題不是相對成本,是 SLO 是否被滿足。延遲若超過 SLO,就要選「接受高延遲」或「合併兩個子領域到同一服務(犧牲團隊自主)」。
- 執行期耦合風險:某些操作的執行期耦合可透過調整邊界消除,某些則必須改變語意(例如 partial outcome 或非同步)才能解決;再次,只有當它讓 SLO 不滿足時才是問題。
- 最終一致性的複雜:傳統 2PC 在現代應用不適用——本身就是執行期耦合,且許多現代資料庫不支援 2PC。較好的做法是把 ACID 限定在單一服務內,跨服務操作以「一連串本地交易」實作,即「最終一致性」。
- 缺點:更複雜的交易模型;不能依賴 DB 鎖與 rollback;有時要寫補償邏輯;併發要在應用層處理;跨服務查詢無法強一致。
- 工具:四個服務協作模式——Saga、Command-side replica(分散式 commands);API Composition、CQRS(分散式 queries),第 10、11 章詳述。

Figure 7.9: Distributed transactions are replaced with a sequence of local transactions coordinated by asynchronous messaging
跨服務變更很複雜#
單一服務變更比巨石快、簡單,但跨多個服務的變更比巨石更複雜:
- 向後相容變更:有部署順序依賴(被依賴方先上線,client 才能用)。
- 破壞性 API 變更:必須做 3 步——加新版、client 全部遷移、刪舊版,遠比巨石中改一個 commit 多。
設計時的核心目標:讓多數變更局限在單一服務內。要做到這點本身就是一大挑戰。
設計微服務架構很困難#
軟體設計的核心是命名、分群、貫徹鬆耦合與高內聚。微服務的設計特別不寬容於錯誤——服務是行程與交易邊界,把兩個被同一系統操作呼叫的子領域分開部署,影響遠比把兩個類別分到不同 package 嚴重。
一不小心就做出分散式巨石:服務間設計期緊耦合(改動連鎖)+ 執行期緊耦合(失敗連鎖),把兩種架構的缺點集大成。
第 20 章探討這個複雜的設計空間:N 個現有服務時,新子領域有 N+1 種放置方式;每種放置方式又有多種系統操作實作模式,各有取捨,且取捨之間常彼此衝突。
營運挑戰#
巨石的部署架構是「同一應用的多個實例」;微服務則是「多個服務 × 多個實例 × 不同(版本的)技術棧」,且容易出現由獨立服務間互動引起的「emergent behavior(突現行為)」。
容器、Kubernetes、現代可觀測性工具能緩解相當多複雜度,但「消化複雜度」永遠是團隊責任。
擁抱獨立部署是組織重大改變#
- 組織常死守應用層級 user acceptance test,讓「獨立部署」實質失效——這是分散式巨石的常見成因。
- 解法:把這類測試重構為服務層級的 user acceptance test——以白盒方式驗證每個服務在隔離下的行為。
- 例:Order Service 的 acceptance test 驗證
createOrder()用預期參數呼叫reserveCredit(),並正確處理 success / unknown customer / insufficient credit 等結果。 - Consumer Service 的 acceptance test 驗證
reserveCredit()在不同信用額度下的行為。
- 例:Order Service 的 acceptance test 驗證
- 結構上,測試套件的拆解 mirror 應用架構的拆解;許多服務層級 acceptance test 還可寫成快速本地單元測試。

Figure 7.10: Refactor application-level acceptance tests into service-level acceptance tests that test each service in isolation
「服務一起測試 ⇒ 你正在打造分散式巨石」。要嘛改善架構讓服務能各自獨立測試,要嘛乾脆做巨石——折中路線最糟。
巨石遷移到微服務很困難#
需要長期投入(常以「年」為單位),解開 legacy 程式碼、處理大型應用的複雜度——好處夠大才值得(策略與技巧見第 21 章)。
微服務架構模式語言#
Christopher Alexander 在《A Pattern Language: Towns, Buildings, Construction》(1977)為實體建築建立 253 個模式組成的語言;Erich Gamma 等的《Design Patterns》(1994)把這個概念引入軟體領域。
一個模式(pattern) 是針對特定情境下重複出現問題的可重用解決方案。
模式的核心結構#
一個寫得好的模式應包含:
- Forces:在該情境下解決問題時必須處理的關注點;forces 可彼此衝突,優先順序由情境決定。
- Resulting context:套用後的後果——好處(被解決的 forces)、壞處(未解決的 forces)、新引入的問題。
- Related patterns:與其他模式的關係,有五種:predecessor、successor、alternative、generalization、specialization。

Figure 7.11: Visual representation of pattern relationships — predecessor, successor, alternative, generalization, specialization
微服務架構模式語言的高層結構#
模式語言分三層:
- Infrastructure patterns:多在開發以外的基礎設施範疇。
- Application infrastructure patterns:同時影響開發。
- Application patterns:服務開發者面對的問題。

Figure 7.12: A high-level view of the microservice architecture pattern language showing problem areas
主要模式群組:
- Application architecture patterns:Monolithic vs Microservice。
- Service collaboration patterns:四個——Saga、Command-side replica(commands);API Composition、CQRS(queries)。詳見第 10、11 章。
- Communication patterns(五群):
- Communication style(同步 RPC/REST 或非同步 messaging)
- Transactional messaging(訊息收送與業務交易整合)
- Reliability(同步通訊在服務或網路有問題時仍可靠)
- Discovery(client 如何知道某服務實例的網路位置)
- External API(外部 client 怎麼跟服務溝通)

Figure 7.13: Five groups of communication patterns — communication style, transactional messaging, reliability, discovery, external API
- Security patterns:常見如 Access Token——API gateway 以 JWT 等令牌把使用者身份與角色傳遞給服務。
- Patterns for automated testing:Consumer-driven contract test、Consumer-side contract test、Service component test(第 15、16 章)。
- Service deployment patterns:傳統手動部署無法支撐;需要高度自動化的部署平台(GitOps、容器、無伺服器等),第 12、{chapter-kubernetes} 章詳述。

Figure 7.14: Patterns for deploying microservices — language-specific, VM/container, serverless, deployment platform
- Observability patterns:Health check API、Log aggregation、Distributed tracing、Exception tracking、Application metrics、Audit logging。
- Cross-cutting concerns:Service Template 與 Microservice Chassis——降低每個服務重新實作 logging、security、monitoring 等共通邏輯的負擔,並維持一致性。
章節重點摘要#
- 微服務架構不只是服務的集合:還包括跨服務的系統操作、部署管線/建置架構、服務與團隊的對應關係。
- 微服務的好處(多源於鬆耦合與獨立可部署):支援流暢交付的五個品質屬性、改善開發體驗、支援多技術棧、讓組織能擴張、用「依特徵切分子領域」改善可用性、安全性、可擴展性等。
- 分散式架構是雙面刃:跨服務的系統操作(latency、partial failure、最終一致性)是主要挑戰來源。
- 成功採用必須有意識的設計,避免做出分散式巨石(緊耦合服務,集兩種架構的劣勢)。
- 團隊必須擁抱「獨立可部署」,以服務隔離測試取代應用層級 acceptance test。
- 微服務架構模式語言提供「該不該用微服務」與「真的要用,該怎麼解一系列衍生問題」的設計指引。