# 閘道器與反向代理原理
::: tip 🎯 核心問題
**在高併發的網際網路架構中，如何把流量安全、高效地送到正確的服務？** 反向代理解決「流量怎麼分發」，API 閘道器解決「請求怎麼處理」。本文透過真實案例（櫃檯接待、保全系統、智慧路由）深入理解閘道器的設計哲學和工程實務。
:::

---

## 1. 要「閘道器」的動機

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

某電商平台在業務快速成長時遇到了嚴重的架構問題：

**場景還原：**

```
階段一：直接暴露服務
客戶端 → 直接呼叫使用者服務、訂單服務、支付服務...
         ↓
問題1：服務 IP 暴露，存在安全隱患
問題2：無法統一做認證、限流
問題3：新增服務需要修改客戶端組態
```

::: warning ⚠️ 直接暴露的致命問題

- **安全隱患**：所有服務 IP 暴露，容易被攻擊
- **功能重複**：每個服務都要做認證、限流、日誌
- **擴充困難**：新增服務要修改所有客戶端
- **協定混亂**：有的用 HTTP，有的用 gRPC，客戶端要適配
  :::

**改進後的架構（引入閘道器）：**

```
客戶端 → API 閘道器（Nginx/Kong） → 內部服務
         ↓
      統一認證、限流、路由
         ↓
      客戶端只知道閘道器位址
```

::: tip ✨ 改進後的效果

- **安全**：真實服務 IP 隱藏，只有閘道器對外
- **功能收斂**：認證、限流、日誌在閘道器統一處理
- **擴充容易**：新增服務只需閘道器組態路由
- **協定統一**：對外 HTTP，內部可用 gRPC
  :::

### 1.2 閘道器的生活化比喻

**櫃檯接待**

想像你去一家大公司：

- **沒有櫃檯**：訪客直接找各部門，不知道在哪，公司亂成一團
- **有櫃檯**：訪客先到櫃檯，櫃檯問清楚來意，再引導到對應部門

**API 閘道器就是系統的「櫃檯」**：

- **反向代理**：櫃檯，引導訪客到正確的部門
- **API 閘道器**：智慧櫃檯，還能檢查訪客身分（認證）、限制存取人數（限流）

<ReverseProxyDemo />

---

## 2. 反向代理 概述

### 2.1 正向代理 vs 反向代理

::: tip 🤔 術語解釋
**正向代理（Forward Proxy）**：

- 部署在客戶端側
- 代替客戶端存取外部資源
- 典型應用：VPN、翻牆工具
- 例子：公司網路，你透過代理存取外網

**反向代理（Reverse Proxy）**：

- 部署在伺服器端
- 接收客戶端請求並轉發給內部服務
- 客戶端只知道代理存在，不知道真實伺服器
- 例子：Nginx、HAProxy
  :::

**對比表：**

| 維度         | 正向代理                 | 反向代理                 |
| ------------ | ------------------------ | ------------------------ |
| **部署位置** | 客戶端側                 | 伺服器端                 |
| **服務對象** | 客戶端                   | 伺服器                   |
| **典型應用** | VPN、翻牆                | 負載平衡、閘道器         |
| **透明性**   | 伺服器看到代理 IP        | 客戶端看到代理 IP        |
| **目的**     | 隱藏真實客戶端、加速存取 | 隱藏真實伺服器、負載平衡 |

### 2.2 反向代理的核心價值

::: details 價值一：負載平衡
將流量分發到多個後端伺服器，避免單點過載。

```
客戶端
  ↓
Nginx（反向代理）
  ↓
┌─────────┬─────────┬─────────┐
│ 伺服器1 │ 伺服器2 │ 伺服器3 │
└─────────┴─────────┴─────────┘
```

:::

::: details 價值二：安全防護
隱藏真實伺服器 IP，防止直接攻擊。統一在代理層做安全防護。

```
客戶端 → 只能看到 Nginx 的 IP
真實伺服器 → 只在內網，外部無法直接存取
```

:::

::: details 價值三：SSL 終結
在代理層處理 HTTPS 加密解密，後端服務用 HTTP，降低後端計算開銷。

```
HTTPS 客戶端 → Nginx（加密/解密） → HTTP 後端服務
                   ↑
              SSL 終結點
```

:::

---

## 3. Nginx：能扛起百萬併發的動機

### 3.1 Master-Worker 行程模型

Nginx 採用**多行程**架構，而不是多執行緒：

**Master 行程（管理者）**：

- 負責讀取和驗證設定檔
- 管理 Worker 行程（啟動、停止、重新載入）
- 不處理具體請求

**Worker 行程（工作者）**：

- 實際處理 HTTP 請求
- 每個 Worker 是獨立的行程，相互隔離
- 數量通常設定為 CPU 核心數，避免上下文切換開銷

::: tip 💡 優勢

- **隔離性好**：一個 Worker 崩潰，不影響其他 Worker
- **充分利用多核**：每個 Worker 獨立執行
- **避免多執行緒複雜性**：無需處理鎖、競爭等問題
  :::

### 3.2 事件驅動 + 非同步非阻塞

這是 Nginx 高效能的核心秘密：

**傳統 Apache（多行程/執行緒模型）**：

- 一個連線 = 一個行程/執行緒
- 併發數受限於系統行程/執行緒數
- 大量連線時，行程切換開銷巨大

**Nginx（事件驅動模型）**：

- 使用 epoll（Linux）/ kqueue（macOS）等高效 I/O 多工機制
- 一個 Worker 行程可以同時處理數萬個連線
- 連線沒有資料時，不會佔用 CPU，有新資料時透過事件通知喚醒

::: tip 生活化比喻

- **Apache**：餐廳裡每個顧客配一個服務生（行程），顧客多需要大量服務生
- **Nginx**：一個超級服務生，同時服務所有顧客，誰需要服務就去誰那裡，而不是一直站在某個顧客旁邊
  :::

<NginxArchitectureDemo />

---

## 4. API 閘道器 概述

### 4.1 需要 API 閘道器的動機

**想像一個沒有閘道器的系統：**

- 客戶端需要知道多個服務的位址（使用者服務、訂單服務、支付服務...）
- 每個服務都要自己做認證、限流、日誌
- 協定不統一，有的用 HTTP，有的用 gRPC
- 服務升級時，客戶端也需要跟著改

::: warning ⚠️ 沒有閘道器的問題

- **客戶端複雜**：需要組態多個服務位址
- **功能重複**：每個服務都要實作認證、限流
- **協定混亂**：客戶端要適配多種協定
- **升級困難**：服務升級，客戶端也要改
  :::

**有了 API 閘道器之後：**

- 客戶端只需要知道閘道器位址，閘道器負責路由到正確服務
- 認證、限流、日誌等橫切邏輯統一在閘道器處理
- 閘道器可以做協定轉換，對外統一暴露 HTTP
- 後端服務升級，只需要改閘道器組態，客戶端無感知

<ApiGatewayDemo />

### 4.2 API 閘道器的核心功能

| 功能         | 說明                                       | 典型場景                                         |
| :----------- | :----------------------------------------- | :----------------------------------------------- |
| **路由轉發** | 根據 URL、Header 等規則，將請求轉發到不同服務 | `/api/users` → 使用者服務，`/api/orders` → 訂單服務 |
| **負載平衡** | 同一個服務有多執行個體時，分攤流量              | 使用者服務有 3 台執行個體，輪詢分發請求                   |
| **認證鑑權** | 統一校驗 JWT、OAuth Token                   | 未登入使用者無法存取 `/api/admin`                   |
| **限流熔斷** | 控制流量上限，防止服務被壓垮                | 每秒最多 1000 請求，超過回傳 429                     |
| **協定轉換** | 對外 HTTP，內部可轉 gRPC                      | 客戶端用 HTTP，閘道器轉 gRPC 呼叫內部服務              |
| **灰度發布** | 按 Header 或比例，將部分流量導到新版本        | 5% 使用者體驗新版本，95% 用舊版本                     |
| **日誌監控** | 統一記錄請求日誌，便於分析和排除故障            | 記錄每次請求的耗時、狀態碼、回傳大小             |

---

## 5. 閘道器實戰：構建完整的閘道器架構的方法

### 5.1 完整架構圖

```
┌───────────────────────────────────────────────────────────────────────┐
│                           客戶端（瀏覽器/APP）                               │
└───────────────────────────┬─────────────────────────────────────────┘
                                │ HTTPS
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                        外層：CDN + WAF                                  │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  CDN（內容分發網路）                                        │  │
│  │  - 靜態資源快取（圖片、CSS、JS）                           │  │
│  │  - 就近存取，降低延遲                                   │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  WAF（Web 應用防火牆）                                     │  │
│  │  - 防護 SQL 注入、XSS 攻擊                                │  │
│  │  - 攔截惡意 Bot、爬蟲                                  │  │
│  │  - CC 攻擊防護                              │  │
│  └───────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                     中層：API 閘道器（Nginx/Kong）                      │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第一層：SSL 終結 + 安全防護                              │  │
│  │  - HTTPS / TLS 1.3                                        │  │
│  │  - HSTS、安全回應頭                                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第二層：認證與鑑權                                      │  │
│  │  - JWT Token 校驗                                         │  │
│  │  - OAuth 2.0 / SSO 整合                                     │  │
│  │  - API Key 管理                                         │  │
│  │  - 權限校驗（RBAC）                                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第三層：流量控制                                        │  │
│  │  - 限流 - 令牌桶/漏桶演算法                             │  │
│  │  - 熔斷 - 防止故障擴散                                 │  │
│  │  - 降級 - 服務不可用時的備用方案                         │  │
│  │  - 灰度發布 - 按比例分配流量                          │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第四層：路由與負載平衡                                    │  │
│  │  - 路徑路由 - Path-based Routing）                          │  │
│  │  - 域名路由 - Host-based Routing）                           │  │
│  │  - Header 路由 - Header-based Routing）                             │  │
│  │  - 負載平衡演算法 - 輪詢/加權/最少連線/IP 雜湊）             │  │
│  │  - 服務發現 - Service Discovery）整合                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第五層：協定轉換與資料處理                                 │  │
│  │  - SSL 終結 - HTTPS ↔ HTTP）                                   │  │
│  │  - 協定轉換 - HTTP ↔ gRPC / WebSocket）                         │  │
│  │  - 請求/回應轉換 - JSON ↔ XML）                               │  │
│  │  - 資料壓縮 - Gzip / Brotli）                                   │  │
│  │  - 快取 - Cache）- 靜態資源和 API 回應                          │  │
│  └───────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                        內層：微服務叢集                             │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐      │
│  │  使用者服務    │ │  訂單服務    │ │  商品服務    │ │  支付服務    │      │
│  │  User Svc   │ │  Order Svc  │ │ Product Svc │ │ Payment Svc │      │
│  │             │ │             │ │             │ │             │      │
│  └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘      │
│         │                │                │                │               │
│         └────────────────┴────────────────┴────────────────┘               │
│                                       │                              │
│                    服務發現與組態中心 / etcd）                          │
│                    - 服務註冊與發現                                      │
│                    - 健康檢查                                              │
│                    - KV 組態儲存                                              │
└───────────────────────────────────────────────────────────────────────┘
```

### 5.2 路由與負載平衡

閘道器的核心職責之一，就是**把請求送到正確的地方**。這涉及兩個關鍵能力：**路由**（去哪台伺服器）和**負載平衡**（怎麼分配流量）。

::: details 路由規則：從 URL 到服務
想像一個電商系統，不同的 URL 對應不同的服務：

- `/api/users/*` → 使用者服務
- `/api/orders/*` → 訂單服務
- `/api/products/*` → 商品服務
- `/api/pay/*` → 支付服務

**Nginx 組態範例：**

```nginx
server {
    listen 80;
    server_name api.example.com;

    # 使用者服務
    location /api/users/ {
        proxy_pass http://user-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 訂單服務
    location /api/orders/ {
        proxy_pass http://order-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 商品服務
    location /api/products/ {
        proxy_pass http://product-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 支付服務（需要更高安全級別）
    location /api/pay/ {
        # 限制 IP 存取
        allow 10.0.0.0/8;
        deny all;

        proxy_pass http://payment-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
```

:::

::: details 負載平衡：四種策略對比
當同一個服務有多個執行個體時，如何選擇？

| 策略         | 原理                                              | 適用場景           | 優點                 | 缺點                         |
| :----------- | :------------------------------------------------ | :----------------- | :------------------- | :--------------------------- |
| **輪詢**     | 按順序依次分配給每台伺服器                        | 伺服器效能相近     | 簡單公平             | 不考慮伺服器當前負載         |
| **加權輪詢** | 按權重比例分配，權重高的分配更多                   | 伺服器效能不均     | 充分利用高效能伺服器 | 需要合理設定權重             |
| **最少連線** | 分配給當前連線數最少的伺服器                      | 長連線場景、影片串流 | 動態適應負載變化     | 需要即時統計連線數           |
| **IP 雜湊**  | 根據客戶端 IP 計算雜湊，同一 IP 永遠分配到同一台伺服器 | 需要工作階段保持       | 保證工作階段一致性         | 某個 IP 流量大時會造成單點壓力 |

**Nginx 組態範例：**

```nginx
# 加權輪詢
upstream backend_weighted {
    server 10.0.1.10:8080 weight=3;  # 效能好，承擔更多流量
    server 10.0.1.11:8080 weight=2;
    server 10.0.1.12:8080 weight=1;  # 效能差，承擔較少流量
}

# 最少連線
upstream backend_least_conn {
    least_conn;
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

# IP 雜湊（工作階段保持）
upstream backend_ip_hash {
    ip_hash;
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}
```

:::

<LoadBalancingDemo />

---

## 6. 閘道器安全：守護系統大門的方法

### 6.1 認證與鑑權

**傳統方式（每個服務各自認證）：**

- 使用者服務、訂單服務、支付服務...每個都要校驗 JWT
- 程式碼重複，維護困難
- secret 分散在各個服務，洩露風險高

**閘道器統一認證：**

- 客戶端攜帶 Token 存取閘道器
- 閘道器校驗 Token 合法性（簽章、過期時間）
- 校驗通過後，將使用者資訊（如 user_id）新增到請求頭，轉發給後端服務
- 後端服務無需校驗，直接從 Header 取得使用者資訊

::: tip 💡 核心思想
**認證在閘道器，鑑權在服務**：

- **認證**：你是誰？（校驗 Token，取得使用者身分）
- **鑑權**：你能做什麼？（根據使用者角色判斷權限）

就像公司櫃檯：櫃檯認證你的身分（身分證），但具體權限由各部門判斷。
:::

<AuthMiddlewareDemo />

### 6.2 HTTPS 與 SSL 終結

**為什麼需要 HTTPS？**

1. **安全**：防止資料在傳輸過程中被竊取
2. **合規**：現代瀏覽器對 HTTP 網站顯示「不安全」警告
3. **SEO**：搜尋引擎優先收錄 HTTPS 網站

**SSL 終結方案：**

- 只在閘道器層組態 HTTPS 和憑證
- 閘道器負責 TLS 握手和加解密
- 閘道器和後端服務之間使用 HTTP 明文傳輸（內部網路可信）
- 後端服務專注於業務邏輯，無需處理 TLS

::: tip 💡 SSL 終結的優勢

- **簡化管理**：憑證只在閘道器組態，後端無需組態
- **降低開銷**：後端服務不需要處理 TLS 握手
- **統一更新**：憑證更新只需在閘道器操作
  :::

<SslTerminationDemo />

---

## 7. 限流與熔斷：防止系統被「流量洪水」沖垮的方法

### 7.1 限流演算法對比

| 演算法         | 核心思想                  | 突發流量                    | 適用場景                       | 實作複雜度 |
| :----------- | :------------------------ | :-------------------------- | :----------------------------- | :--------- |
| **令牌桶**   | 桶裡裝令牌，有令牌才能通過 | 允許一定程度的突發          | API 限流、頻寬控制              | 中等       |
| **漏桶**     | 請求進桶，勻速流出處理     | 強制平滑，突發會被快取或拒絕 | 需要嚴格勻速處理的場景         | 中等       |
| **滑動視窗** | 統計時間視窗內的請求數    | 嚴格按視窗計數，超出一律拒絕 | 精確統計（如「1 分鐘內最多 100 次」） | 較高       |

### 7.2 Nginx 限流組態實戰

```nginx
# 定義限流區域（放在 http 塊中）

# 1. 基於 IP 的限流（漏桶演算法）
# zone=mylimit:10m - 區域名稱和記憶體大小（10MB 約可儲存 16 萬 IP）
# rate=10r/s - 每秒允許 10 個請求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

# 2. 基於 IP 的連線數限制（防止單個 IP 建立過多連線）
limit_conn_zone $binary_remote_addr zone=addr:10m;

# 3. 基於服務端點的限流（不區分 IP，保護後端整體）
limit_req_zone $server_name zone=server_limit:10m rate=100r/s;

server {
    listen 80;
    server_name api.example.com;

    # 使用者服務 - 普通限流
    location /api/users/ {
        # 應用限流
        # burst=20 - 桶容量，允許突發 20 個請求
        # nodelay - 不延遲處理突發請求（立即處理或拒絕）
        limit_req zone=mylimit burst=20 nodelay;

        # 限制單個 IP 的連線數
        limit_conn addr 10;

        proxy_pass http://user-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 訂單服務 - 更嚴格的限流
    location /api/orders/ {
        # 更嚴格的限流：每秒 5 個請求
        limit_req_zone $binary_remote_addr zone=order_limit:10m rate=5r/s;
        limit_req zone=order_limit burst=10 nodelay;

        proxy_pass http://order-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 限流後的處理
    # 當請求被限流時，回傳 429 Too Many Requests
    error_page 429 /429.html;
    location = /429.html {
        internal;
        return 429 '{"error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}';
        add_header Content-Type application/json;
    }
}
```

::: tip 💡 限流策略建議

- **普通介面**：每秒 10 個請求，允許突發 20 個
- **重要介面**（支付、訂單）：每秒 5 個請求，允許突發 10 個
- **全域保護**：所有請求總和不超過每秒 100 個
  :::

<RateLimitingDemo />

### 7.3 熔斷：防止故障擴散

**熔斷器的工作原理：**

1. **關閉狀態**：正常轉發請求，同時統計錯誤率
2. **開啟狀態**：當錯誤率超過閾值，熔斷器開啟，直接回傳錯誤，不再轉發請求
3. **半開狀態**：經過一段時間後，允許少量請求通過試探，如果成功則關閉熔斷器

::: tip 💡 核心思想
**熔斷就像電路保險絲**：電流過大時，保險絲自動熔斷，保護整個電路不被燒毀。

類似地，當後端服務出現大量錯誤時，熔斷器「跳閘」，快速失敗，防止故障擴散到整個系統。
:::

---

## 8. 總結：閘道器設計的核心思維

### 8.1 核心原則回顧

| 原則         | 含義                 | 實務要點                       |
| ------------ | -------------------- | ------------------------------ |
| **路由**     | 把請求送到正確的地方 | 路徑路由、域名路由、Header 路由 |
| **負載平衡** | 分攤流量到多台伺服器 | 輪詢、加權、最少連線、IP 雜湊   |
| **安全**     | 守護系統大門         | 認證鑑權、HTTPS、WAF           |
| **限流**     | 防止被流量沖垮       | 令牌桶、漏桶、滑動視窗         |
| **熔斷**     | 防止故障擴散         | 快速失敗、降級方案             |
| **可觀測**   | 監控和排除故障           | 日誌、指標、鏈路追蹤           |

### 8.2 技術選型建議

::: tip 💡 選型決策樹

```
選擇閘道器：
│
├─ 只需要反向代理、負載平衡？
│  ├─ 是 → Nginx（首選）
│  └─ 否 → 繼續
│
├─ 需要豐富的外掛生態？
│  ├─ 是 → Kong（基於 Nginx）
│  └─ 否 → 繼續
│
├─ Spring Cloud 全家桶？
│  ├─ 是 → Spring Cloud Gateway
│  └─ 否 → Nginx
```

:::

---

## 9. 名詞速查表

| 名詞         | 英文                     | 解釋                                                                                                               |
| ------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| **反向代理** | Reverse Proxy            | 部署在伺服器端，接收客戶端請求並轉發給內部服務的代理服務。客戶端只知道反向代理的存在，不知道真實伺服器位址。         |
| **正向代理** | Forward Proxy            | 部署在客戶端側，代替客戶端存取外部資源的代理服務。伺服器端看到的是代理的 IP，不知道真實客戶端。典型應用：VPN、翻牆工具。 |
| **API 閘道器**  | API Gateway              | 位於客戶端和後端服務之間的中間層，提供路由、認證、限流、日誌等功能，是微服務架構的「統一大門」。                       |
| **負載平衡** | Load Balancing           | 將請求流量分配到多台伺服器，避免單台伺服器過載，提高系統可用性和效能。                                               |
| **SSL 終結**  | SSL Termination          | 在閘道器層處理 HTTPS 加密解密，後端服務使用 HTTP，降低後端計算開銷，簡化憑證管理。                                         |
| **限流**     | Rate Limiting            | 限制單位時間內的請求數量，防止系統被突發流量壓垮。常用演算法：令牌桶、漏桶、滑動視窗。                                 |
| **熔斷**     | Circuit Breaking         | 當依賴服務出現故障時，自動切斷呼叫，防止故障擴散，並提供降級方案。                                                    |
| **工作階段保持** | Session Persistence      | 確保同一客戶端的請求始終路由到同一台後端伺服器，用於需要保持工作階段狀態的場景。                                        |
| **健康檢查** | Health Check             | 定期檢查後端服務的健康狀態，自動剔除故障節點，保證流量只發送到健康的服務執行個體。                                       |
| **灰度發布** | Canary Release           | 將少量流量導到新版本，驗證穩定性後逐步擴大比例，降低發布風險。                                                       |
| **WAF**      | Web Application Firewall | Web 應用防火牆，防護 SQL 注入、XSS、CC 攻擊等 Web 安全威脅。                                                              |
| **CDN**      | Content Delivery Network | 內容分發網路，在全球部署邊緣節點，加速靜態資源存取。                                                                 |