結論先講
WS 和 SSE 的壓測結果出乎意料地無聊——因為所有框架都能撐。 9 個框架在 WebSocket 500 VU 全部零錯誤,SSE 200 VU 也全部零錯誤。Express-TS 和 Go 在 WS 1000 VU 仍然零錯誤,p95 只有 2ms。如果你在選框架時糾結「哪個框架的 WebSocket 比較好」——答案是「都一樣好」。
這和 CRUD 場景 的結論完全相反。CRUD 場景 500 VU 全部崩潰,WS 場景 500 VU 全部健康。差異在於:CRUD 每個 request 都要算 bcrypt(CPU-bound),WS 只是維持一條 TCP 連線(幾乎零 CPU 成本)。
WebSocket 壓測
測試場景
| 項目 | 設定 |
|---|---|
| 流程 | 建立 WS 連線 → ping/pong heartbeat → 維持連線 |
| VU | 1000 VU 同時建立連線 |
| 框架 | 9 個全部參與 |
結果
| 框架群組 | 500 VU | 1000 VU |
|---|---|---|
| Express-TS | 零錯誤 | 零錯誤,p95 2ms |
| Go | 零錯誤 | 零錯誤 |
| 其他 7 框架 | 全部零錯誤 | 部分開始有壓力 |
為什麼 WS 這麼「輕」
WebSocket 連線建立後就是一條 TCP 長連線。維持一條連線的成本:
- 記憶體:每條連線約 50KB(buffer + 狀態)
- CPU:幾乎為零(只有 ping/pong 的 heartbeat,幾 ms 一次)
- I/O:接近零(idle 連線沒有資料傳輸)
1000 條連線 × 50KB = 50MB 記憶體。在 2GB Docker 限制下綽綽有餘。
對比 CRUD:每個 request 需要 ~100ms CPU 做 bcrypt。1000 VU 同時打 bcrypt = 2 核 CPU 完全飽和。
WS 的瓶頸不在「能撐多少連線」,而在「能同時廣播多少訊息」。 建立連線是免費的,推送訊息才有成本。
Express-TS 的 p95 2ms 代表什麼
p95 2ms 是 ping/pong 的 roundtrip 時間——從 server 送 ping 到收到 pong。2ms 在 Docker bridge network 內是正常的(幾乎等於網路延遲本身)。這代表 Express-TS 的 WS 處理沒有引入額外的延遲。
SSE 壓測
測試場景
| 項目 | 設定 |
|---|---|
| 流程 | 建立 SSE 連線 → 接收 server 推送的 keepalive 事件 |
| VU | 500 VU 同時建立連線 |
| 連線維持 | 每條連線保持約 10 秒 |
結果
| 框架群組 | 200 VU | 500 VU |
|---|---|---|
| 所有 9 框架 | 全部零錯誤 | Express-TS 零錯誤 |
p95 10 秒不是延遲
SSE 的 p95 顯示約 10 秒——這不是延遲,是連線保持時間。k6 把整個 SSE 連線的 duration 記錄下來,一條保持 10 秒的連線就會顯示 p95 = 10s。
真正的延遲指標應該看「從 server 推送事件到 client 收到」的時間,通常在 1-5ms 之間。
SSE vs WebSocket 的差異
| 維度 | WebSocket | SSE |
|---|---|---|
| 方向 | 雙向 | 單向(server → client) |
| 協議 | ws:// 升級協議 | 純 HTTP |
| 重連 | 需要自己做 | 瀏覽器自動重連 |
| 適合 | 聊天室、協作編輯 | AI 串流回應、即時通知、股價 |
| 複雜度 | 高(狀態管理) | 低(只是 HTTP 長連線) |
SSE 比 WS 簡單很多——不需要處理升級協議、不需要管理連線狀態、瀏覽器原生支援自動重連。 如果你的場景只需要 server 推送(AI 串流回應就是),用 SSE 就好,不需要上 WS。
和 CRUD/混合場景的對照
| 場景 | 500 VU 表現 | 瓶頸 |
|---|---|---|
| CRUD | 全部崩潰(0% 但堵塞) | bcrypt CPU-bound |
| 混合 | 部分框架健康 | bcrypt + I/O |
| 檔案上傳 | Spring Boot/Go 健康 | I/O + 記憶體 |
| WebSocket | 全部零錯誤 | 沒有瓶頸(連線維持成本極低) |
| SSE | 全部零錯誤 | 沒有瓶頸 |
框架的效能差異主要在 CPU-bound 操作(bcrypt、JSON 序列化、ORM 查詢)。 純 I/O 操作(連線維持、ping/pong)所有框架都一樣快。
這也解釋了 免費午餐篇 的結論:如果你的應用是 WS/SSE 為主(聊天、通知),框架選型不重要,選你最熟的就好。如果你的應用有 Auth + CRUD 操作,框架選型才有意義。
WS/SSE 的真正瓶頸在哪
壓測顯示 1000 VU 的連線建立和維持不是問題。真正的瓶頸在生產環境中是:
1. 訊息廣播效率
1000 人在聊天室,一個人發訊息 → server 要把這條訊息推給另外 999 人。推的速度和框架的 event loop / thread pool 效率有關。
2. 記憶體管理
每條 WS 連線約 50KB。1 萬條 = 500MB、10 萬條 = 5GB。在容器化環境下,記憶體是比 CPU 更先觸及的限制。
3. 跨節點通訊
水平擴展後,用戶 A 連到 server 1,用戶 B 連到 server 2。A 發訊息給 B 需要跨 server 通訊。這時候需要 Redis Pub/Sub 或 Kafka 做訊息中繼。
這些瓶頸和「選哪個框架」無關——它們是架構層面的問題(呼應 Infra 擴展篇)。
下一篇
Queue、Redis Cache、Cold Start:剩下的三場測試 — Queue 的差異在生態不在速度。Redis cache 開了都有提升。Cold Start Go 最快 6.7 秒、NestJS 最慢 30.3 秒——Serverless 選型的關鍵數據。
本系列文章
完整 68 篇目錄見 系列首頁
← 上一篇:檔案上傳壓測:Streaming vs Buffering 的哲學之爭 → 下一篇:Queue、Redis Cache、Cold Start:最後三場測試