API 閘道(API Gateway)是微服務架構中至關重要的基礎設施組件。它作為系統的統一入口,承擔著路由、安全、限流等關鍵職責。本章節將深入探討 API 閘道的原理、功能與實作。

為什麼需要 API 閘道#

微服務架構的挑戰#

在微服務架構中,內部通常包含多個獨立的服務模組(如購物車服務、庫存服務、推薦服務、訂單服務等),這些服務由不同的團隊獨立維護。

對於外部客戶端而言:

  • 不應該直接感知到後端複雜的服務拓撲結構
  • 不應該需要知道每個服務的地址
  • 不應該處理跨服務的通用邏輯(如認證、限流)

API 閘道的核心價值#

API 閘道對外提供一個「統一的介面」。無論後端有多少個微服務在運作,外部使用者面對的只是一個統一的服務入口。這不僅簡化了客戶端的呼叫邏輯,也保護了內部架構的隱私與安全。

flowchart TB
    subgraph Clients["外部客戶端"]
        C1["Web App"]
        C2["Mobile App"]
        C3["Third Party"]
    end

    Clients --> GW["API Gateway<br/>(統一入口)"]

    GW --> S1["用戶服務"]
    GW --> S2["訂單服務"]
    GW --> S3["商品服務"]

    style GW fill:#fff3e0

API 閘道的部署架構#

典型的請求鏈路#

從部署視圖來看,API 閘道通常位於負載均衡器與內部微服務之間:

flowchart TB
    L1["1. 用戶接入層<br/>無線設備、桌面應用、伺服器等"]
    L2["2. 負載均衡層<br/>接收外部流量並分發"]
    L3["3. API 閘道層<br/>處理路由、認證等邏輯"]
    L4["4. 微服務層<br/>實際的業務邏輯處理單元"]

    L1 --> L2 --> L3 --> L4

    style L1 fill:#e3f2fd
    style L2 fill:#e8f5e9
    style L3 fill:#fff3e0
    style L4 fill:#f3e5f5

高可用設計原則#

為了確保系統的高可用性,通常會在閘道前置一層負載均衡器。這要求閘道本身設計為「無狀態(Stateless)」的。

無狀態設計的優勢

  • 允許閘道進行水平擴展(Scale-out)
  • 即使某一台閘道實例故障,流量可以無縫切換至其他存活節點
  • 避免單點故障(SPOF)
  • 保障整體系統的穩定性

API 閘道的四大核心功能#

1. 反向路由 (Reverse Routing)#

這是閘道最基本的功能。當外部請求進入時,閘道需要根據請求的特徵(如 URL 路徑),將其精準地「導航」並轉換為內部具體服務的呼叫。

路由組態示例

routes:
  - path: /api/users/**
    service: user-service
  - path: /api/orders/**
    service: order-service
  - path: /api/products/**
    service: product-service

路由策略

策略說明
路徑匹配根據 URL 路徑前綴路由
Header 匹配根據請求頭資訊路由
參數匹配根據查詢參數路由
權重路由按比例分配流量(用於灰度發布)

2. 安全認證 (Security Authentication)#

如同門衛負責識別訪客身份,閘道是防禦惡意攻擊的第一道防線。

主要職責

功能說明
請求過濾區分正常用戶訪問與惡意爬蟲、黑客攻擊
身份驗證驗證請求者的身份(如 JWT Token 驗證)
權限校驗檢查請求者是否有權限訪問目標資源
統一認證在請求到達後端服務之前,集中處理認證

認證流程示例

flowchart TD
    A["1. 客戶端發送請求<br/>(攜帶 Token)"] --> B["2. 閘道提取並驗證 Token"]
    B -->|驗證失敗| C["返回 401 Unauthorized"]
    B -->|驗證成功| D["3. 提取用戶資訊"]
    D --> E["4. 將用戶資訊注入請求頭"]
    E --> F["5. 轉發請求到後端服務"]

    style C fill:#ffcdd2
    style F fill:#c8e6c9

3. 限流與熔斷 (Rate Limiting & Circuit Breaking)#

應對突發流量(如「雙 11」大促、秒殺活動)的關鍵機制。

限流 (Rate Limiting)

當大流量洪峰湧入時,如果沒有防護措施,後端服務極易癱瘓。閘道需實施限流策略,拒絕超過系統負荷的請求。

常見限流算法:

算法特點
令牌桶允許一定程度的突發流量
漏桶流量輸出速率恆定
固定窗口簡單但可能有臨界點問題
滑動窗口更精確但實作複雜

熔斷 (Circuit Breaking)

當後端某個服務出現不穩定時,閘道可快速切斷對該服務的呼叫,防止故障擴散導致雪崩效應。

stateDiagram-v2
    [*] --> Closed: 初始狀態
    Closed --> Open: 失敗率超過閾值
    Open --> HalfOpen: 經過一段時間
    HalfOpen --> Closed: 嘗試請求成功
    HalfOpen --> Open: 嘗試請求失敗

    note right of Closed: 正常狀態
    note right of Open: 快速失敗<br/>不呼叫後端服務
    note right of HalfOpen: 嘗試少量請求

4. 日誌監控 (Logging & Monitoring)#

由於所有外部流量都必須經過閘道,這使其成為資料採集的最佳位置。

主要功能

功能說明
訪問審計對所有請求進行記錄與審計
效能分析通過分析日誌,監控呼叫延遲、成功率等指標
流量統計統計各服務的訪問量、峰值等
異常告警檢測異常模式並觸發告警

閘道過濾器架構#

以 Netflix Zuul 為例#

Zuul 的請求處理流程通過一系列的過濾器來完成,主要分為三個階段:

flowchart TD
    A[請求進入] --> B[Pre-routing Filters<br/>前置過濾器]
    B --> |日誌處理<br/>路由決策<br/>參數校驗| C[Routing Filters<br/>路由過濾器]
    C --> |服務呼叫<br/>網路請求| D[Post-routing Filters<br/>後置過濾器]
    D --> |響應加工<br/>統計審計<br/>日誌記錄| E[響應返回]

    B -.-> |異常| F[Error Filters<br/>錯誤處理]
    C -.-> |異常| F
    D -.-> |異常| F
    F --> E

    style B fill:#e3f2fd
    style C fill:#fff3e0
    style D fill:#e8f5e9
    style F fill:#ffebee

在 Pre、Routing、Post 的任一環節中,若發生錯誤或拋出異常,流程會轉交給 Error Filters 進行全域的錯誤處理與訊息封裝,確保客戶端能收到格式統一的錯誤回應。

動態過濾器機制#

閘道作為流量入口,通常承受巨大的訪問壓力,不適合頻繁重啟。但業務需求往往需要頻繁調整閘道邏輯。

Zuul 的解決方案:使用 Groovy 腳本編寫過濾器,支援動態載入。

過濾器動態上傳與載入流程
  1. 上傳 (Upload):開發人員編寫 Groovy 過濾器腳本,上傳至過濾器儲存資料庫
  2. 輪詢 (Polling):Filter Poller 定期輪詢資料庫,檢查是否有新增或更新的過濾器
  3. 下載 (Download):若發現變更,Poller 將腳本下載至本地特定目錄
  4. 掃描與載入 (Scan & Load)
    • Filter File Manager 定期掃描本地目錄
    • 發現新文件,呼叫 Filter Loader 動態載入 Groovy 腳本
    • 最終註冊到 Zuul Filter Runner 中,新邏輯立即生效

請求上下文共享#

由於請求會流經多級過濾器,需要在不同階段之間傳遞資料。

Request Context

  • 基於 ThreadLocal 實作
  • 允許在單次請求的生命週期內,讓 Pre、Routing、Post 等各階段的過濾器共享狀態與資訊

閘道設計的權衡#

瘦閘道 vs 胖閘道#

在實際的架構演進中,關於閘道的職責邊界往往存在爭議:是否應該在 API 閘道層引入「業務邏輯」?

瘦閘道 (Thin Gateway) - 推薦

特點說明
職責專注於路由、限流、安全等通用基礎設施功能
業務邏輯完全下沉到微服務中
穩定性更穩定,升級維護不依賴具體業務團隊
發布發布頻率低,風險可控

胖閘道 (Fat Gateway)

特點說明
職責包含聚合接口(BFF)或部分業務校驗邏輯
問題容易成為單體瓶頸
發布不同業務團隊的程式碼糾纏,嚴重拖慢發布效率

建議保持閘道「輕量化」。若需處理複雜的資料聚合,可考慮引入獨立的 BFF (Backend for Frontend) 層,而不是將邏輯塞入全域的 API 閘道中。

BFF 模式#

當需要為不同的前端(Web、iOS、Android)提供定製化的 API 時,可以採用 BFF 模式:

flowchart TB
    subgraph Apps["客戶端應用"]
        A1["Web App"]
        A2["iOS App"]
        A3["Android App"]
    end

    subgraph BFFs["BFF 層"]
        B1["Web BFF"]
        B2["iOS BFF"]
        B3["Android BFF"]
    end

    A1 --> B1
    A2 --> B2
    A3 --> B3

    B1 --> GW
    B2 --> GW
    B3 --> GW

    GW["API Gateway"] --> MS["後端微服務"]

    style BFFs fill:#e3f2fd
    style GW fill:#fff3e0

常見的 API 閘道實作#

Netflix Zuul#

特點

  • 基於 Servlet,運行於 Tomcat 容器
  • 過濾器架構,支援動態載入
  • Spring Cloud 早期默認閘道

Spring Cloud Gateway#

特點

  • 基於 Spring WebFlux,非阻塞
  • 響應式編程模型
  • Spring Cloud 新一代閘道

Kong#

特點

  • 基於 Nginx + Lua
  • 豐富的插件生態
  • 支援聲明式組態

APISIX#

特點

  • 基於 Nginx + Lua
  • 雲原生友好
  • 高效能
API 閘道選型對比
特性Zuul 1.xSpring Cloud GatewayKongAPISIX
效能中等極高
協議支援HTTPHTTP, WebSocketHTTP, gRPCHTTP, gRPC
組態方式程式碼程式碼/組態聲明式聲明式
插件機制FilterFilterPluginPlugin
語言JavaJavaLuaLua
雲原生一般良好良好優秀

實踐建議#

閘道設計清單#

考量點建議
無狀態設計確保閘道實例可以水平擴展
健康檢查組態完善的健康檢查機制
超時設置合理設置連接超時和讀取超時
重試策略組態合理的重試策略,避免重試風暴
限流粒度根據業務需求選擇合適的限流粒度
監控告警建立完善的監控和告警機制
灰度發布支援基於權重或規則的灰度發布
文檔管理與 API 文檔系統(如 Swagger)集成

常見問題與解決方案#

問題解決方案
閘道成為效能瓶頸水平擴展 + 效能最佳化
組態變更需要重啟引入動態組態機制
跨域問題在閘道層統一處理 CORS
請求體過大組態合理的請求體大小限制
長連接支援選擇支援 WebSocket 的閘道