結論先講
大部分應用不需要微服務。 單體 + Redis + nginx + multi-worker 能撐 UV 500-1000。真的需要拆的信號不只是「撐不住」,還有「團隊太大改不動」和「不同模組需要不同的擴展策略」。
從壓測數據推算單體上限
裸單體
| 框架 | 2 CPU 健康 UV | 4 CPU 估計 |
|---|---|---|
| Go | 100-500 | 500-1000 |
| Express-TS (PM2×4) | 50-100 | 200-500 |
| Spring Boot | 50(CRUD)/ 1000(混合) | 200-2000 |
| Django | 10-50 | 100-200 |
+ 免費午餐(Redis + keepalive + multi-worker)
第 21 篇 的組合提升約 13 倍。保守估計 5-10 倍:
| 框架 | 裸單體 | + 免費午餐 |
|---|---|---|
| Go | 500 | 2500-5000 |
| Express-TS | 100 | 500-1000 |
| Spring Boot | 1000 | 5000-10000 |
| Django | 50 | 250-500 |
Spring Boot 單體 + 免費午餐理論上能撐到 5000-10000 人。 大部分應用永遠到不了這個數字。
拆分決策樹
你的單體撐不住了嗎?
├── 沒有(UV < 單體上限)
│ └── 不要拆。做免費午餐。
│
├── 有,但免費午餐還沒做完
│ └── 先做免費午餐。做完再看。
│
├── 有,免費午餐都做了還是撐不住
│ ├── 瓶頸在哪?
│ │ ├── DB → 先做讀寫分離 + 連線池調整
│ │ ├── CPU (bcrypt) → 降 rounds 或換 Argon2
│ │ ├── 記憶體 → 調 Docker limits
│ │ └── 全部都到頂了 → 考慮拆
│ │
│ └── 團隊太大改不動了嗎?
│ ├── 是(> 10 人,改 A 功能要碰 B 的 code)→ 拆
│ └── 不是 → 水平擴展(加機器,不拆服務)
三個拆的信號
- 效能天花板:免費午餐 + 水平擴展(2-4 台)都做了,還是不夠
- 開發瓶頸:團隊 > 10 人,改一個功能要跨三個模組,PR 互相衝突
- 擴展需求不同:Auth 需要 CPU(bcrypt),File 需要記憶體(圖片),Post 需要 DB 連線——不應該共享同一池資源
三個不要拆的信號
- 「聽說微服務很潮」:不是技術理由
- 團隊 < 5 人:微服務的運維成本會吃掉小團隊的所有時間
- 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 漸進式替換