結論先講

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 → 維持連線
VU1000 VU 同時建立連線
框架9 個全部參與

結果

框架群組500 VU1000 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 事件
VU500 VU 同時建立連線
連線維持每條連線保持約 10 秒

結果

框架群組200 VU500 VU
所有 9 框架全部零錯誤Express-TS 零錯誤

p95 10 秒不是延遲

SSE 的 p95 顯示約 10 秒——這不是延遲,是連線保持時間。k6 把整個 SSE 連線的 duration 記錄下來,一條保持 10 秒的連線就會顯示 p95 = 10s。

真正的延遲指標應該看「從 server 推送事件到 client 收到」的時間,通常在 1-5ms 之間。

SSE vs WebSocket 的差異

維度WebSocketSSE
方向雙向單向(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/SubKafka 做訊息中繼。

這些瓶頸和「選哪個框架」無關——它們是架構層面的問題(呼應 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:最後三場測試