結論先講

大部分應用不需要微服務。 單體 + Redis + nginx + multi-worker 能撐 UV 500-1000。真的需要拆的信號不只是「撐不住」,還有「團隊太大改不動」和「不同模組需要不同的擴展策略」。


從壓測數據推算單體上限

裸單體

框架2 CPU 健康 UV4 CPU 估計
Go100-500500-1000
Express-TS (PM2×4)50-100200-500
Spring Boot50(CRUD)/ 1000(混合)200-2000
Django10-50100-200

+ 免費午餐(Redis + keepalive + multi-worker)

第 21 篇 的組合提升約 13 倍。保守估計 5-10 倍:

框架裸單體+ 免費午餐
Go5002500-5000
Express-TS100500-1000
Spring Boot10005000-10000
Django50250-500

Spring Boot 單體 + 免費午餐理論上能撐到 5000-10000 人。 大部分應用永遠到不了這個數字。


拆分決策樹

你的單體撐不住了嗎?
├── 沒有(UV < 單體上限)
│   └── 不要拆。做免費午餐。
│
├── 有,但免費午餐還沒做完
│   └── 先做免費午餐。做完再看。
│
├── 有,免費午餐都做了還是撐不住
│   ├── 瓶頸在哪?
│   │   ├── DB → 先做讀寫分離 + 連線池調整
│   │   ├── CPU (bcrypt) → 降 rounds 或換 Argon2
│   │   ├── 記憶體 → 調 Docker limits
│   │   └── 全部都到頂了 → 考慮拆
│   │
│   └── 團隊太大改不動了嗎?
│       ├── 是(> 10 人,改 A 功能要碰 B 的 code)→ 拆
│       └── 不是 → 水平擴展(加機器,不拆服務)

三個拆的信號

  1. 效能天花板:免費午餐 + 水平擴展(2-4 台)都做了,還是不夠
  2. 開發瓶頸:團隊 > 10 人,改一個功能要跨三個模組,PR 互相衝突
  3. 擴展需求不同:Auth 需要 CPU(bcrypt),File 需要記憶體(圖片),Post 需要 DB 連線——不應該共享同一池資源

三個不要拆的信號

  1. 「聽說微服務很潮」:不是技術理由
  2. 團隊 < 5 人:微服務的運維成本會吃掉小團隊的所有時間
  3. UV < 免費午餐上限:先做簡單的事

如果決定拆,怎麼拆

第一刀:最痛的那個模組先拆

不要一次全拆。找到最大的瓶頸,先拆它:

  • bcrypt 是瓶頸 → 先拆 Auth Service
  • 圖片上傳吃記憶體 → 先拆 File Service
  • 搜尋查詢慢 → 先拆 Search Service(可能用 Elasticsearch)

共用 DB 先,分 DB 後

第 28 篇 我們的經驗:先拆 process(獨立服務),DB 先共用。等穩定了再考慮分 DB。

Phase 1: 拆 process,共用 DB
  - 風險低(不需要處理跨 DB 一致性)
  - 每個 service 可以獨立部署
  - 可以獨立分配 CPU/記憶體

Phase 2: 分 DB
  - 需要 event-driven(第 35-36 篇)
  - 需要 saga pattern(第 46-47 篇)
  - 複雜度大幅上升

準備好才拆

拆之前確認你有:

  • 集中 log(不然 debug 噩夢,第 28 篇
  • 監控 dashboard(Grafana,第 5 篇
  • CI/CD pipeline(每個 service 獨立部署)
  • Event-driven 架構(至少有 Redis + BullMQ)

缺任何一個,拆了之後會比不拆更痛。


下一篇

微服務拆分模式:Strangler Fig、Branch by Abstraction — 決定要拆了,具體怎麼拆?不是「重寫」而是「漸進式替換」。Strangler Fig pattern 讓你一個模組一個模組地把單體變成微服務,不需要 big bang。


本系列文章

完整 68 篇目錄見 系列首頁

← 上一篇:框架選型實戰案例:50 人、500 人、5000 人分別選什麼 → 下一篇:微服務拆分模式:Strangler Fig 漸進式替換