# 負載平衡與閘道器原理
::: tip 🎯 核心問題
**當單台伺服器扛不住時，如何把流量「聰明地」分配到多個伺服器執行個體？** 負載平衡是現代分散式系統的「分發員」。本文透過真實案例（飲料店收銀、快遞分揀、交通指揮）深入理解負載平衡的設計哲學和工程實踐。
:::

---

## 1. 要「負載平衡」的動機

### 1.1 從一個真實案例說起：某網站的架構演進

某創業公司在使用者量快速增長時遇到了嚴重的效能問題：

**情境還原：**

```
階段一：單台伺服器
使用者 → 伺服器（1 核 2G）
       ↓
    日活 1000 → 活躍時間：1000 人同時存取
       ↓
問題：CPU 100%，回應慢，經常當機
```

::: warning ⚠️ 單台伺服器的致命問題

- **效能瓶頸**：CPU 100%，回應時間 > 5 秒
- **單點故障**：伺服器掛了，整個網站無法使用
- **擴充困難**：只能垂直升級（加 CPU、記憶體），貴且有限
  :::

**改進後的架構（引入負載平衡）：**

```
階段二：多台伺服器 + 負載平衡
使用者 → 負載平衡器（Nginx）
       ↓
     ├→ 伺服器 1（1 核 2G）
     ├→ 伺服器 2（1 核 2G）
     └→ 伺服器 3（1 核 2G）
```

::: tip ✨ 改進後的效果

- **效能提升**：3 台伺服器並行處理，回應時間 < 1 秒
- **高可用性**：1 台伺服器掛了，其他伺服器繼續服務
- **水平擴充**：需要更多效能？加伺服器就行
  :::

### 1.2 負載平衡的生活化比喻

**飲料店收銀台**

想像你開了一家網紅飲料店：

- **1 個收銀台**：顧客排隊，後面的人等不及，負評
- **3 個收銀台**：員工分配顧客到不同收銀台，效率提升 3 倍

**負載平衡就是「收銀台分配員」**：

- **使用者**（顧客） → 請求服務
- **負載平衡器**（分配員） → 把請求分配到不同伺服器
- **伺服器**（收銀台） → 處理請求

<LoadBalancerTypesDemo />

---

## 2. 負載平衡 概述

### 2.1 四層負載平衡（L4）：只看門牌號碼

**工作在傳輸層（TCP/UDP）**，就像快遞員只看你家的**門牌號碼（IP 位址 + 連接埠號）**，不關心你家是做什麼的。

**特點：**

- **速度超快**：只做簡單的位址轉送，不解析資料封包內容
- **適用情境**：資料庫連線、Redis 快取、長連線遊戲伺服器
- **代表產品**：LVS（Linux Virtual Server）、AWS NLB、Azure Load Balancer

::: details 工作原理

```
用戶端請求 → L4 負載平衡器 → 後端伺服器
              ↓
         只看 IP + Port
              ↓
         快速轉送（不拆封包內容）
```

:::

### 2.2 七層負載平衡（L7）：檢查構建產物內容

**工作在應用層（HTTP/HTTPS）**，就像快遞員不僅看門牌號碼，還會**打開包裹檢查內容**，根據內容決定怎麼送。

**特點：**

- **智慧路由**：可以根據 URL 路徑、HTTP 標頭、Cookie 等做精細化路由
- **進階功能**：SSL 卸載、內容快取、壓縮、安全 WAF
- **適用情境**：Web 應用、API 閘道器、微服務架構
- **代表產品**：Nginx、HAProxy、AWS ALB、Envoy

::: details 工作原理

```
用戶端請求 → L7 負載平衡器 → 解析 HTTP 內容
              ↓
         檢查 URL、Header、Cookie
              ↓
         智慧路由到特定伺服器
```

:::

### 2.3 L4 vs L7 對比一覽

| 維度           | 四層負載平衡（L4）     | 七層負載平衡（L7）          |
| :------------- | :------------------- | :------------------------ |
| **工作層級**   | 傳輸層（TCP/UDP）      | 應用層（HTTP/HTTPS）        |
| **決策依據**   | IP 位址 + 連接埠號      | URL、Header、Cookie、Body |
| **處理速度**   | 極快（核心態處理）     | 較快（使用者態解析）          |
| **功能豐富度** | 基礎轉送             | SSL 卸載、快取、壓縮、WAF  |
| **典型情境**   | 資料庫、遊戲、長連線 | Web 應用、API 閘道器、微服務  |
| **代表產品**   | LVS、AWS NLB         | Nginx、HAProxy、AWS ALB   |

---

## 3. 核心問題一：避免「壞掉」的伺服器繼續承接流量的方法

### 3.1 健康檢查：別讓「生病」的伺服器拖累系統

想像一下，你的某個收銀台突然壞了，但分配員不知道，還在源源不絕地把顧客分過去。結果隊伍越來越長，顧客怨聲載道。

**健康檢查（Health Check）就是防止這種情況發生的「哨兵」**。它定期「體檢」每台伺服器，發現「生病」的立即從佇列中移除，等「康復」了再請回來。

<!-- <HealthCheckDemo /> -->

### 3.2 主動健康檢查 vs 被動健康檢查

**主動健康檢查（Active Health Check）**：負載平衡器主動「敲門」問伺服器「你還在嗎？」

- 定期傳送探測請求（如 HTTP /health、TCP ping）
- 回應逾時或傳回錯誤碼則認為不健康
- **優點**：檢測結果準確可靠
- **缺點**：產生額外的探測流量

**被動健康檢查（Passive Health Check）**：負載平衡器「觀察」真實業務流量的回應情況

- 統計實際請求的回應時間、錯誤率
- 連續多次失敗則認為不健康
- **優點**：不產生額外流量
- **缺點**：需要足夠的流量樣本才能判定

::: details 閾值設定表
| 指標 | 健康閾值 | 不健康閾值 | 說明 |
|:---|:---|:---|:---|
| **HTTP 狀態碼** | 200-399 | 400+ 或逾時 | 4xx/5xx 都認為失敗 |
| **TCP 連線** | 成功建立 | 連線逾時 | 檢查連接埠是否可達 |
| **回應時間** | < 500ms | > 2000ms | 逾時時間通常設為 2-5 秒 |
| **連續失敗次數** | - | 3 次 | 避免單次抖動誤判 |
| **檢查間隔** | - | 5s | 太頻繁會增加負載 |

::: tip 💡 常見踩坑：閾值設定太「敏感」
某團隊將健康檢查的回應時間閾值設為 100ms，而他們的應用平均回應時間在 80-120ms 之間波動。結果是伺服器頻繁被標記為「不健康」，導致流量在健康和不健康之間反覆橫跳，系統整體可用率反而下降。

**正確的做法**：閾值應該設定為 **P99 回應時間的 2-3 倍**，給正常波動留出足夠的緩衝空間。
:::

---

## 4. 核心問題二：保證「老顧客」一直找同一個後端實例的方法

### 4.1 工作階段保持：讓「老顧客」一直找同一個後端實例

想像你是飲料店的常客，每次來都由同一個店員接待。她知道你的口味偏好（半糖、去冰），服務起來又快又貼心。但如果每次來都換一個新人，你得一遍遍重複同樣的要求，效率大打折扣。

**工作階段保持（Session Persistence / Sticky Session）** 就是解決這個問題的方法：確保同一個使用者的請求，始終被路由到同一台後端伺服器。

<SessionPersistenceDemo />

### 4.2 三種工作階段保持機制對比

| 機制           | 實作原理                                  | 優點                            | 缺點                          | 適用情境                |
| :------------- | :---------------------------------------- | :------------------------------ | :---------------------------- | :---------------------- |
| **Cookie 插入** | LB 在回應中插入 Cookie，後續請求攜帶此 Cookie | 不受 IP 變化影響，首次請求即可保持 | 用戶端需支援 Cookie，可能被停用 | 電商購物車、登入態保持  |
| **IP 雜湊**     | 對用戶端 IP 做雜湊計算，對應到特定伺服器     | 無需用戶端支援，無狀態           | IP 變化會遺失工作階段，難以均勻分布 | 無 Cookie 環境、WebSocket |
| **黏性工作階段表** | LB 維護工作階段到伺服器的對應表                | 支援工作階段複製和故障轉移          | 佔用 LB 記憶體，需要額外同步       | 高可用性要求嚴格的場景    |

::: tip 💡 使用建議

- **Cookie 插入**：優先推薦，相容性好
- **IP 雜湊**：只用於 WebSocket 等特殊情境
- **黏性工作階段表**：配合 Cookie，提供故障轉移能力
  :::

---

## 5. 核心問題三：實現零停機部署的方法

### 5.1 藍綠部署：「一鍵切換」的零停機發布

**核心思想**：同時維護兩套完全相同的生產環境（藍環境和綠環境），但只有一個環境對外提供服務。

<BlueGreenDeploymentDemo />

**工作流程：**

1. **初始狀態**：藍環境執行 v1.0（生產），綠環境待命。
2. **部署新版本**：在綠環境部署 v1.1，進行內部冒煙測試。
3. **切換流量**：將負載平衡器指向綠環境，流量瞬間切換到 v1.1。
4. **監控觀察**：觀察綠環境執行狀態，確認無異常。
5. **保留舊版本**：藍環境保持 v1.0 一段時間（如 24 小時），作為快速復原的保險。

::: tip ✨ 優缺點分析
| 優點 | 缺點 |
|:---|:---|
| ✅ 零停機時間，切換在毫秒級完成 | ❌ 資源成本高，需要同時維護兩套環境 |
| ✅ 快速復原，發現問題立即切回原環境 | ❌ 資料庫 Schema 變更時需要特別處理相容性 |
| ✅ 新環境可完整測試後再接管流量 | ❌ 不適用於有狀態服務（如 WebSocket 長連線） |

:::

### 5.2 金絲雀發布：「小步快跑」的灰度策略

金絲雀發布得名於歷史上的「煤礦金絲雀」——礦工帶著金絲雀下礦井，如果金絲雀出現異常，說明有毒氣體外洩，礦工立即撤離。在軟體發布中，金絲雀發布就是先讓一小部分使用者試用新版本，觀察沒有問題後再逐步擴大範圍。

<CanaryReleaseDemo />

**核心思想：**

1. **小流量先行**：先將 1% 的流量導入新版本伺服器。
2. **觀察指標**：持續監控錯誤率、延遲、業務關鍵指標。
3. **逐步放量**：如果一切正常，逐步將比例提升到 5%、10%、25%、50%、100%。
4. **快速復原**：一旦發現異常，立即將所有流量切回舊版本。

::: tip 💡 金絲雀發布的優勢
| 優勢 | 說明 |
|:---|:---|
| 🎯 **風險可控** | 即使新版本有嚴重 Bug，也只影響少量使用者 |
| 📊 **真實驗證** | 在真實生產環境驗證，比測試環境更可靠 |
| 🚀 **快速迭代** | 團隊可以更自信地頻繁發布新功能 |
| 💰 **資源友善** | 不需要像藍綠部署那樣準備兩套完整環境 |

:::

---

## 6. 核心問題四：讓系統自動彈性伸縮的方法

### 6.1 自動擴縮容：讓系統像餐廳一樣「靈活排班」

想像你開了一家餐廳：

- **午餐尖峰時段**：需要 10 個服務生，但下午 3 點離峰時段只需要 2 個
- 如果一直維持 10 個\*\*：人事成本爆炸
- 如果一直只有 2 個：尖峰時段顧客等不及，全跑了

**自動擴縮容（Auto Scaling）** 就是讓系統像餐廳一樣「靈活排班」——忙的時候自動加伺服器，閒的時候自動減伺服器。

<AutoScalingDemo />

### 6.2 擴充指標的選擇

自動擴縮容的核心是回答一個問題：\*\* **什麼時候該加機器？什麼時候該減機器？**

常見的決策指標：

| 指標                | 擴充閾值   | 縮減閾值   | 適用情境         |
| :------------------ | :--------- | :--------- | :--------------- |
| **CPU 使用率**       | > 70%      | < 30%      | 計算密集型應用   |
| **記憶體使用率**      | > 75%      | < 40%      | 記憶體密集型應用   |
| **QPS（每秒請求數）** | > 1000/s   | < 400/s    | API 閘道器、Web 服務 |
| **連線數**          | > 5000     | < 1000     | 資料庫、訊息佇列 |
| **自訂業務指標**  | 視業務而定 | 視業務而定 | 特定業務情境     |

::: tip 💡 擴充策略的「坑」與「解」

**坑 1：擴充反應太慢，流量洪峰已經把系統打掛了**

某電商大促期間，設定 CPU > 80% 觸發擴充，但監控擷取有 1 分鐘延遲，新執行個體啟動需要 3 分鐘。結果流量來得太快，擴充還沒完成，伺服器已經被打掛。

**解決方案：**

- **提前擴充**：基於歷史資料預測流量尖峰，提前 30 分鐘開始擴充
- **多級閾值**：設定 60% 預警（開始預熱新執行個體）、70% 正式擴充、80% 緊急擴充
- **快速擴充**：使用容器化部署，新執行個體 30 秒內啟動（相比虛擬機器 3-5 分鐘）

**坑 2：擴充太激進，成本爆炸**

某創業公司設定了激進的自動擴充策略：CPU > 50% 就擴充。結果一個正常的業務波動就觸發了擴充，伺服器數量從 5 台膨脹到 30 台，月底雲端帳單嚇哭了 CTO。

**解決方案：**

- **設定擴充冷卻時間**：一次擴充後，至少等待 5 分鐘才能再次擴充
- **設定最大執行個體數**：max = 目前執行個體數 × 2，防止無限膨脹
- **區分突刺和趨勢**：只有連續 3 個週期都超過閾值才擴充，避免單點突刺觸發

**坑 3：縮減太快，剛擴充的機器馬上就縮了**

某團隊設定了 CPU < 30% 縮減。擴充後流量還在消化，CPU 短暫回落到 25%，觸發了縮減。剛縮完 CPU 又飆到 80%，又觸發擴充——系統在「擴充-縮減-擴充」中瘋狂震盪。

**解決方案：**

- **縮減更保守**：擴充閾值 70%，縮減閾值 25%，中間有足夠的緩衝帶
- **縮減冷卻時間更長**：擴充後至少等待 10 分鐘才能縮減
- **漸進式縮減**：一次只縮 1 台，觀察後再決定要不要繼續縮
  :::

---

## 7. 實戰：選擇負載平衡器的方法

### 7.1 主流負載平衡器對比

| 特性           | Nginx                           | HAProxy               | Envoy          | 雲端廠商負載平衡 |
| -------------- | ------------------------------- | --------------------- | -------------- | -------------- |
| **定位**       | 高效能反向代理/負載平衡         | 開源負載平衡          | 雲端原生代理     | 託管負載平衡   |
| **效能**       | 極高（C 語言，事件驅動）            | 高（事件驅動）          | 高（C++/Rust）   | 極高           |
| **功能豐富度** | 基礎負載平衡、靜態檔案、快取    | 豐富的負載平衡演算法    | 進階路由、觀測 | 功能全面       |
| **組態設定**       | 設定檔（nginx.conf）            | 設定檔（haproxy.cfg） | API/設定檔   | UI 主控台       |
| **擴充**       | C 模組/Lua 指令碼                   | Lua 指令碼               | WASM/Filter    | 外掛程式           |
| **適用情境**   | 靜態資源、七層負載平衡、SSL 終結 | 七層負載平衡、高可用性  | 服務網格、多雲端 | 快速上手       |

::: tip 💡 選型建議
**決策樹：**

```
選擇負載平衡器：
│
├─ 只需要基礎的四層負載平衡？
│  ├─ 是 → LVS（開源免費）或 雲端廠商 NLB
│  └─ 否 → 繼續
│
├─ 需要服務網格、多雲端部署？
│  ├─ 是 → Envoy
│  └─ 否 → 繼續
│
├─ 需要極其複雜的組態設定和外掛程式？
│  ├─ 是 → HAProxy
│  └─ 否 → 繼續
│
├─ 需要高效能 + 簡單組態設定？
│  ├─ 是 → Nginx（首選）
│  └─ 繼續
│
├─ 想要託管維運？
│  ├─ 是 → 雲端廠商負載平衡（AWS ALB、阿里雲 SLB）
│  └─ Nginx 自建
```

:::

---

## 8. 總結：負載平衡的核心思維

### 8.1 核心原則回顧

| 原則     | 含義                       | 實踐要點                              |
| -------- | -------------------------- | ------------------------------------- |
| **分層** | L4 處理「快遞分揀」（快但簡單） | L4 處理資料庫、遊戲；L7 處理 Web、API     |
| **冗餘** | 單點故障是架構的敵人       | 透過多執行個體、多區域部署提升可用性      |
| **漸進** | 發布新版本不要「一刀切」     | 藍綠部署實現零停機；金絲雀實現風險可控 |
| **彈性** | 系統應該像生命體一樣「呼吸」 | 忙時自動擴充，閒時自動縮減             |

### 8.2 設計檢查清單

在引入負載平衡前，問自己以下問題：

- [ ] 是否真的需要負載平衡？（單機效能是否真的不夠）
- [ ] 選擇 L4 還是 L7？（根據業務情境）
- [ ] 如何處理工作階段保持？（Cookie、IP 雜湊、工作階段表）
- [ ] 如何實現健康檢查？（主動、被動、閾值設定）
- [ ] 如何實現零停機？（藍綠部署、金絲雀）
- [ ] 如何實現彈性？（擴縮指標、冷卻時間、最大執行個體數）

---

## 9. 名詞速查表

| 名詞             | 英文                                      | 解釋                                                                 |
| ---------------- | ----------------------------------------- | -------------------------------------------------------------------- |
| **負載平衡器**   | Load Balancer                             | 將流量分發到多個後端伺服器的裝置或軟體                               |
| **四層負載平衡** | L4 Load Balancing                         | 基於傳輸層（TCP/UDP）的負載平衡                                        |
| **七層負載平衡** | L7 Load Balancing                         | 基於應用層（HTTP/HTTPS）的負載平衡                                     |
| **健康檢查**     | Health Check                              | 定期檢查後端伺服器的健康狀態的機制                                   |
| **工作階段保持**     | Session Persistence                       | 確保同一使用者的請求始終路由到同一台伺服器                             |
| **黏性工作階段**     | Sticky Session                            | 另一種稱呼，同 Session Persistence                                    |
| **藍綠部署**     | Blue-Green Deployment                     | 兩套環境切換的零停機發布策略                                         |
| **金絲雀發布**   | Canary Release                            | 小流量先行驗證的灰度發布策略                                         |
| **自動擴縮容**   | Auto Scaling                              | 根據負載自動增加或減少伺服器數量                                     |
| **水平擴充**     | Horizontal Scaling                        | 增加伺服器數量來提升處理能力                                         |
| **垂直擴充**     | Vertical Scaling                          | 提升單機組態（CPU、記憶體）來提升處理能力                                |
| **多區域**       | Multi-Region                              | 在多個地理區域部署服務                                               |
| **多活**         | Active-Active                             | 多個區域同時對外提供服務                                             |
| **主備**         | Active-Standby                            | 只有一個區域提供服務，其他待命                                       |
| **資料同步**     | Data Replication                          | 跨區域的資料複製機制                                                 |
| **RTO**          | Recovery Time Objective (RTO)             | 復原時間目標，系統故障後需要在多長時間內復原                         |
| **RPO**          | Recovery Point Objective (RPO)            | 復原點目標，系統故障後可以接受的資料遺失量                           |