結論先講
檔案上傳是 I/O-bound 操作,但 bcrypt 仍然出現在 5 個框架的瓶頸標記中。 因為測試流程包含用戶認證。Spring Boot 和 Go 並列第一(健康 VU 1,000),NestJS 第三(500)。Express-TS 因為沒有 reverse proxy 做 connection buffering,健康 VU 直接是 0——不是因為處理慢,是因為連線被打穿。
排名
| # | 框架 | 健康 VU | Max RPS | 瓶頸 | CRUD | 混合 |
|---|---|---|---|---|---|---|
| 1 | Spring Boot | 1,000 | 251 | CPU 密集 | 8th | 1st |
| 2 | Go | 1,000 | 281 | CPU 密集 | 1st | 2nd |
| 3 | NestJS | 500 | 154 | DB 查詢慢 | 4th | 6th |
| 4 | Django | 500 | 61 | Bcrypt | 9th | 5th |
| 5 | .NET Core | 100 | 37 | Bcrypt | 2nd | 4th |
| 6 | Express-JS | 100 | 186 | 連線數上限 | 5th | - |
| 7 | FastAPI | 10 | 30 | Bcrypt | 6th | 3rd |
| 8 | Laravel | 10 | 9 | Bcrypt | 7th | - |
| 9 | Express-TS | 0 | 204 | 連線數上限 | 3rd | - |
三場排名走勢
CRUD 混合 上傳
Go 1st → 2nd → 2nd ← 穩定
Spring 8th → 1st → 1st ← 非 CRUD 場景王者
NestJS 4th → 6th → 3rd ← 上傳場景亮眼
FastAPI 6th → 3rd → 7th ← 上傳場景暴跌
Express 3rd → - → 9th ← 連線數問題
Express-TS 的矛盾數字
Express-TS 健康 VU = 0(最後一名),但 Max RPS = 204(第三高)。怎麼回事?
「連線數上限」瓶頸——Express.js 沒有 connection buffering。大量併發上傳的連線直接灌到 Node.js 的 event loop,超出處理能力時 error rate 立刻飆升。但在 error 發生前的短暫時間內處理速度很快(204 RPS)。
對比 Laravel 前面有 Nginx 做 connection buffering(第 33 篇),Spring Boot 有 Tomcat 的 acceptCount——Express.js 什麼保護都沒有。
教訓:Express.js 上生產一定要在前面加 Nginx。(呼應 Infra 篇 的建議)
FastAPI 從混合第 3 跌到上傳第 7
FastAPI 在混合場景排第 3(健康 VU 100),但在檔案上傳場景跌到第 7(健康 VU 僅 10)。
問題在 python-multipart 的記憶體管理——多個 1MB 檔案同時上傳時 uvicorn worker 記憶體飆升。在 2 GB Docker 限制下很快就到頂。
NestJS 上傳場景意外亮眼
NestJS 從混合場景的第 6 升到上傳的第 3(健康 VU 500, 154 RPS)。Multer 是 Node.js 生態中最成熟的檔案上傳 middleware,加上 PM2 cluster 分攤了記憶體壓力。
Streaming vs Buffering
框架處理上傳檔案的方式分兩派:
| 方式 | 框架 | 記憶體使用 | 吞吐量 |
|---|---|---|---|
| Streaming | Go (io.Reader) | 低且穩定 | 高 |
| Buffering + 暫存檔 | Spring Boot, Django | 中,穩定 | 中高 |
| 記憶體 Buffering | FastAPI, Laravel | 高,不穩定 | 低 |
| Multer(混合) | NestJS, Express | 中 | 中 |
Go 的 io.Reader 介面讓上傳天然是 streaming 的——檔案邊收邊寫,不需要全部讀進 RAM。Spring Boot 的 Servlet multipart 先寫暫存檔再處理,多了一次 disk I/O 但記憶體穩定。
如果你的應用需要處理大量檔案上傳,Go 的 streaming 模型最佳。
三場壓測的綜合觀察
| 框架 | CRUD | 混合 | 上傳 | 一句話 |
|---|---|---|---|---|
| Go | 1st | 2nd | 2nd | 最穩定——不是每次第一但從不墊底 |
| Spring Boot | 8th | 1st | 1st | 非 CRUD 場景王者,JVM 在讀取/I/O 密集下無敵 |
| NestJS | 4th | 6th | 3rd | 波動但整體中上 |
| FastAPI | 6th | 3rd | 7th | 混合場景好,上傳場景差 |
| Django | 9th | 5th | 4th | 穩定上升,給足資源表現不差 |
| .NET Core | 2nd | 4th | 5th | 穩定下降,BCrypt.Net 是軟肋 |
接下來等 WS+SSE、Queue、Redis On/Off、Batch Upload、Cold Start 的數據在平台上整理好,就能繼續寫剩下的 B2E 文章。
下一篇
WebSocket 與 SSE 壓測:所有框架都能撐,差異不在這裡 — HTTP request-response 看完了,接下來看持久連線。WS 和 SSE 的結果出乎意料地無聊——因為所有框架都能撐。
B2E 五場壓測回顧
到這裡,B2E 的主要壓測場景都跑完了。回顧五場的核心發現:
| 場景 | 核心發現 | 詳細篇章 |
|---|---|---|
| CRUD | bcrypt 是所有框架的共同天花板 | [[micro-service/09-crud-overview|#9-14]] |
| 混合場景 | Spring Boot 從第 8 翻盤到第 1 | [[micro-service/24-mixed-overview|#24]] |
| 檔案上傳 | Streaming vs Buffering 決定天花板 | 本篇 |
| WS/SSE | 所有框架都能撐,不是差異點 | [[micro-service/26-websocket-sse|#26]] |
| Queue/Redis/Cold Start | 差異在生態不在速度 | [[micro-service/27-queue-redis-coldstart|#27]] |
跨場景的三個結論:
- 沒有「最好的框架」——Go CRUD 最穩、Spring Boot 混合最強、Express-TS 生態最大
- 免費午餐比換框架效果大([[micro-service/21-infra-free-lunch|#21]]:Redis + keepalive + multi-worker = 13 倍)
- 選框架看場景 + 團隊 + 預算([[micro-service/23-cross-layer-capacity|#23]]:容量規劃表)
本系列文章
完整 68 篇目錄見 系列首頁
← 上一篇:混合場景壓測:Spring Boot 從倒數第二變第一名 → 下一篇:WebSocket 與 SSE 壓測:所有框架都能撐,差異不在這裡