PCA 架構之旅 05 — Microservices 拆分
PCA
很多團隊一上雲就想「微服務化」,結果拆出 20 個服務、每個都要跟另外 19 個講話,變成分散式的單體(distributed monolith)——比原本的 monolith 還難維護。
PCA 考試會考你「什麼時候該拆、邊界怎麼畫、服務之間怎麼溝通」。這一步就是把 SLO 跟 user story 變成實際的服務邊界。
這是 PCA 架構之旅 的第五步。上一篇 04 · SLO / SLI。
為什麼這一步重要
在 PCA case study 題目中怎麼出現
PCA case study 常描述「團隊要獨立部署」「某個模組的流量是其他的 10 倍」「A 功能要每週發版,B 功能半年才動」。這些其實都在暗示服務邊界。題目會要你照這些描述選出合理的拆法,而不是一律丟 GKE。
考生常見錯誤
- 按技術層拆:資料層一個服務、邏輯層一個服務——這是三層式架構,不是微服務。
- 按資料表拆:每張表一個服務,結果一筆訂單要 call 10 個服務。
- 所有服務都同步呼叫:高度耦合、延遲疊加、一個掛全部掛。
核心概念
拆分的三個原則
| 原則 | 說明 |
|---|---|
| 按業務能力(Business Capability) | 一個服務對應一個業務動作,例如「下單」「查詢庫存」 |
| 按變更速率(Rate of Change) | 常改的跟少改的分開,獨立部署 |
| 按擴展特性(Scaling Profile) | 讀多寫少、計算密集、I/O 密集的分開 |
DDD(Domain-Driven Design)基本詞彙
- Bounded Context:一個領域的邊界,例如「訂單」「庫存」「會員」各自是一個 context。
- Aggregate:一個 context 內資料一致性的單位,例如「訂單」是一個 aggregate,底下有品項、金額、狀態。
- Context Map:各個 bounded context 之間的關係圖。
服務間溝通模式
| 模式 | 適用情境 | GCP 對應 |
|---|---|---|
| 同步 REST/gRPC | 即時、強依賴 | Cloud Run + Internal LB、GKE |
| 非同步事件(Pub/Sub) | 解耦、容忍延遲 | Pub/Sub |
| 工作佇列 | 重試、限流 | Cloud Tasks |
| 批次資料管線 | 大量、非即時 | Dataflow、BigQuery |
思考框架
拆分每個服務前先問:
- 這個服務獨立部署時,能給使用者什麼完整價值? 不能就還沒拆對。
- 它擁有的資料是什麼?誰能寫? 一份資料只能有一個 owner 服務。
- 它的 SLO 跟鄰居一樣嗎? 不一樣就該拆。
- 它的 scaling 曲線跟鄰居一樣嗎? 不一樣就該拆。
- 它被呼叫的路徑是同步還是非同步? 同步太深會疊 latency,應考慮事件化。
走一遍範例 — 登雲書店
根據前面的 persona、story、SLO,登雲書店切出 8 個核心服務(bounded context):
服務清單
| # | 服務名 | 職責 | 變更速率 | SLO 重點 |
|---|---|---|---|---|
| 1 | catalog-service | 商品目錄、搜尋 | 中(每週) | 讀多寫少、99.9% |
| 2 | inventory-service | 庫存數量、預留 | 低(每月) | 強一致、99.99% |
| 3 | pricing-service | 定價、促銷 | 高(每日) | 讀多寫少、99.9% |
| 4 | cart-service | 購物車 | 中 | 高 QPS、99.9% |
| 5 | order-service | 訂單生命週期 | 低 | 99.99%、Saga 協調 |
| 6 | payment-service | 金流整合 | 低 | PCI 隔離、99.99% |
| 7 | ebook-service | 電子書閱讀進度 | 中 | 寫多讀多、99.9% |
| 8 | partner-ingest-service | 書商批次匯入 | 低 | 吞吐導向、99% |
邊界拆分的理由
- catalog 跟 inventory 分開:catalog 被大量快取、流量高;inventory 要強一致避免超賣,兩邊的 scaling 特性差很多。
- pricing 獨立:促銷規則常改,又常跟行銷合作要快速上線,所以跟訂單、庫存解耦。
- payment 獨立並放在獨立 project:PCI DSS 要求最小作用域(minimized scope),獨立出來就能只讓這個 project 碰卡號。
- partner-ingest 獨立:批次型,資源用量跟線上服務完全不同,放一起會互相影響。
服務間溝通設計
- 同步呼叫:cart → pricing、cart → inventory(結帳前查詢)。
- 非同步事件:order → payment → order(使用 Pub/Sub 通知結果,避免 order 等 bank API 20 秒)。
- 事件廣播:inventory 變動發
inventory.updatedevent,catalog 與搜尋索引各自訂閱。 - 批次管線:partner-ingest 用 Dataflow 寫入 inventory 與 pricing 的專屬 import table,再交換進入正式表。
共同治理
- 每個服務一個 GCP project 或至少一個 namespace,用 Workload Identity 管 IAM。
- 服務間呼叫走 Internal HTTP(S) LB 或 gRPC;對外只開 API Gateway。
- 共用 schema 放在 single repo 的
schemas/目錄,用 Protobuf + Buf 做版本管理。
常見陷阱
- 拆太細變奈米服務:8 個服務剛好,30 個就是災難。先從 3–5 個開始,跑一陣子看狀況再拆。
- 共用資料庫:兩個服務共用同一張表等於沒拆。每個服務要有自己的儲存。
- 同步呼叫鏈超過 3 跳:A → B → C → D 的同步鏈,一個慢全部慢。超過 3 跳就要考慮事件化。
- 忽略組織結構:Conway’s Law 說系統架構會長得像組織架構。6 人團隊硬切 8 個服務會沒人顧得了。
延伸閱讀
- Microservices.io — Decomposition Patterns — Chris Richardson 的經典拆分方法。
- GCP — What Is Microservices Architecture? — 官方微服務架構概念說明。
- DDD Reference by Eric Evans — DDD 用語官方 PDF。
- SRE Workbook — Non-Abstract Large System Design — 系統分解的 SRE 觀點。
下一步:服務邊界有了,接著就要設計它們對外的契約,也就是 REST API 設計。
🎯 換你練習
理論讀完,換自己來。到 架構師設計工作坊 · 步驟 5 填入你的 case study,邊寫邊內化。
pca-architect-journey — 5/13 完成
查看系列全覽 →