負載平衡 (Load Balancing)

為什麼需要負載平衡?

水平擴展(加更多伺服器)需要告訴客戶端「要跟哪台伺服器溝通」,這就是負載平衡的核心任務。


客戶端負載平衡

客戶端自己決定要連哪台伺服器(透過服務登錄中心或 DNS)。

例子 機制
Redis Cluster 客戶端雜湊 key 決定目標節點,錯誤節點回 MOVED 指引
DNS 輪換 DNS 回傳輪換過的 IP 列表,客戶端依序嘗試

優點:無需額外網路跳點,延遲最低
缺點:客戶端需定期更新伺服器列表,更新有延遲

何時用客戶端 LB

(1) 少量可控制的客戶端(內部微服務、gRPC 客戶端)
(2) 大量客戶端但可容忍緩慢更新(DNS)


專用負載平衡器

位於客戶端和後端之間的獨立元件,每個請求多一跳,換取細粒度控制。

L4 負載平衡器(傳輸層)

Client ──TCP連線──► L4 LB ──TCP連線──► Server
         (維護持久 TCP 連線)
WebSocket 必須用 L4

L7 LB 終止傳入連線再建立新連線,會破壞 WebSocket 的持久連線
WebSocket 必須使用 L4 LB 維護端到端的 TCP 連線。

L7 負載平衡器(應用層)

Client ──HTTP請求──► L7 LB ──轉發HTTP──► Server
         (理解HTTP內容,智慧路由)

L7 LB 典型功能

面試預設選 L7

除 WebSocket 外的所有 HTTP 流量,預設用 L7 LB。


負載平衡演算法

演算法 機制 適合場景
輪詢(Round Robin) 依序分配 無狀態服務、通用
隨機(Random) 隨機選擇 無狀態服務
最少連線(Least Connections) 發到連線數最少的伺服器 持久連線服務(SSE、WebSocket)
最快回應(Least Response Time) 發到回應最快的伺服器 延遲敏感服務
IP 雜湊(IP Hash) 由客戶端 IP 決定 Session 持久性需求
持久連線服務的 LB 陷阱

SSE/WebSocket 等長連線如果用 Round Robin,新加入的伺服器不會分到已建立的連線,舊伺服器會逐漸積累所有連線。
持久連線服務必須用 Least Connections。


健康檢查

LB 自動監控後端伺服器,故障時停止路由:

類型 方式 成本
TCP 健康檢查 檢查是否接受新連線
L7 健康檢查 發 HTTP 請求確認 200 回應 稍高

這是負載平衡器對高可用性至關重要的原因——自動偵測故障並繞道,無需人工介入。


降低全球延遲

CDN(內容傳遞網路)

全球分佈的邊緣伺服器網路,快取靜態內容(圖片、影片、JS/CSS)。

無 CDN:  用戶(台北) ──80ms──► 伺服器(紐約)
有 CDN:  用戶(台北) ──5ms───► 邊緣節點(台北)

適合:可快取性高、需要全球查詢的資料(靜態資源、公開 API 回應)

區域分片(Regional Partitioning)

按地理區域分片資料,讓每個區域只處理相關資料。

Uber 例子:
- 美東區域(資料中心在紐約)← 處理美東的叫車請求
- 美西區域(資料中心在洛杉磯)← 處理美西的叫車請求
- 台北用戶永遠不會叫到紐約的司機 → 跨區查詢不必要

伺服器和資料庫共址(co-located),查詢延遲最低。