前陣子公司微服務集羣擴張到三十多個服務,客户端調用變得一團糟:每個服務都有獨立域名,認證邏輯重複開發,還經常因為某個服務突發流量拖垮整個集羣。後來引入Kong網關作為統一入口,不僅解決了域名混亂問題,還通過流量控制和認證攔截減輕了業務服務的負擔,運維效率提升了不少。

在微服務架構中,API網關扮演着"交通樞紐"的角色,負責請求路由、流量控制、認證授權等橫切關注點。Kong作為基於Nginx的高性能網關,以輕量、可擴展著稱,尤其適合高併發場景。本文結合實際業務場景,講解Kong的核心功能、路由配置技巧以及流量控制策略,幫你快速上手這個強大的網關工具。

一、Kong基礎:核心概念與部署

Kong的核心概念很簡單,理解這幾個術語就能快速入門:

  • Service:代表後端的一個微服務(如用户服務、訂單服務),定義了服務的訪問地址。
  • Route:路由規則,決定哪些請求轉發到哪個Service(如將/api/user/*轉發到用户服務)。
  • Plugin:插件機制,用於實現認證、限流、日誌等功能,可綁定到Service或Route。

快速部署Kong

用Docker Compose快速部署Kong(含PostgreSQL存儲配置):

# docker-compose.yml
version: '3'

services:
  postgres:
    image: postgres:13
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: kong
    volumes:
      - pgdata:/var/lib/postgresql/data

  kong:
    image: kong:3.2
    depends_on:
      - postgres
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: postgres
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kong
      KONG_PROXY_LISTEN: 0.0.0.0:8000
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
    ports:
      - "8000:8000"  # 代理端口(接收客户端請求)
      - "8001:8001"  # 管理端口(配置Kong)
    restart: always

volumes:
  pgdata:

啓動服務:

docker-compose up -d

驗證部署成功:

curl http://localhost:8001/status  # 返回Kong狀態信息

二、路由配置:精準轉發請求

路由是Kong的核心功能,通過定義Route規則,可將不同路徑、方法的請求轉發到對應的微服務。

1. 創建Service(後端服務)

先定義一個指向用户服務的Service:

# 創建用户服務Service
curl -X POST http://localhost:8001/services \
  -d "name=user-service" \
  -d "url=http://user-service:8080"  # 後端服務實際地址

再創建訂單服務:

curl -X POST http://localhost:8001/services \
  -d "name=order-service" \
  -d "url=http://order-service:8080"

2. 配置Route(路由規則)

為用户服務添加路由,匹配/api/user開頭的路徑:

# 用户服務路由:匹配路徑/api/user/*
curl -X POST http://localhost:8001/services/user-service/routes \
  -d "paths[]=/api/user" \
  -d "methods[]=GET" \
  -d "methods[]=POST" \
  -d "name=user-route"

為訂單服務添加路由,同時匹配路徑和主機名:

# 訂單服務路由:匹配主機名order.example.com和路徑/api/order/*
curl -X POST http://localhost:8001/services/order-service/routes \
  -d "paths[]=/api/order" \
  -d "hosts[]=order.example.com" \
  -d "name=order-route"

此時,Kong會按以下規則轉發:

  • GET http://localhost:8000/api/user/1 → 轉發到user-service:8080/api/user/1
  • POST http://order.example.com:8000/api/order → 轉發到order-service:8080/api/order

3. 路由高級配置:路徑重寫

有時需要修改請求路徑,例如將/api/v1/user重寫為/user後轉發到後端:

# 創建帶路徑重寫的路由
curl -X POST http://localhost:8001/services/user-service/routes \
  -d "paths[]=/api/v1/user" \
  -d "name=user-v1-route" \
  -d "strip_path=false"  # 不自動去除匹配的路徑前綴
  -d "regex_priority=2"  # 路由優先級(數字越大越優先)
  -d "plugins[0].name=request-transformer" \
  -d "plugins[0].config.replace.uri[]=/user"  # 將URI重寫為/user

配置後,/api/v1/user/1會被重寫為/user/1轉發到後端服務。

三、流量控制:限流與熔斷

Kong通過插件實現流量控制,防止後端服務被突發流量壓垮,常用的有rate-limiting(限流)和request-size-limiting(請求大小限制)。

1. 接口限流

為用户服務添加限流插件,限制每個IP每分鐘最多100次請求:

# 為user-service添加限流插件
curl -X POST http://localhost:8001/services/user-service/plugins \
  -d "name=rate-limiting" \
  -d "config.minute=100" \  # 每分鐘100次
  -d "config.policy=local" \  # 本地限流(集羣需用redis)
  -d "config.limit_by=ip"  # 按IP限流

超過限制時,Kong會返回429狀態碼:

{
  "message": "API rate limit exceeded"
}

也可針對特定路由限流(如更嚴格限制登錄接口):

# 為登錄路由添加更嚴格的限流
curl -X POST http://localhost:8001/routes/login-route/plugins \
  -d "name=rate-limiting" \
  -d "config.minute=10"  # 每分鐘僅10次

2. 請求大小限制

防止大請求消耗過多資源,限制請求體最大1MB:

curl -X POST http://localhost:8001/services/order-service/plugins \
  -d "name=request-size-limiting" \
  -d "config.allowed_payload_size=1" \  # 1MB
  -d "config.size_unit=megabytes"

超過限制時返回413狀態碼。

3. 熔斷機制

當後端服務頻繁出錯時,自動熔斷避免無效請求:

# 配置熔斷插件:50%失敗率且至少10個請求時觸發
curl -X POST http://localhost:8001/services/payment-service/plugins \
  -d "name=circuit-breaker" \
  -d "config.failure_threshold=50" \  # 失敗率閾值
  -d "config.minimum_calls=10" \  # 最小調用次數
  -d "config.window_size=60" \  # 統計窗口(秒)
  -d "config.fallback=http_status=503"  # 熔斷時返回503

四、認證與安全:統一攔截

Kong可集中處理認證邏輯,避免每個服務重複開發。以JWT認證為例:

1. 啓用JWT插件

為所有服務啓用JWT認證:

# 全局啓用JWT插件(作用於所有服務)
curl -X POST http://localhost:8001/plugins \
  -d "name=jwt" \
  -d "config.uri_param_names[]=token" \  # 支持URL參數傳遞token
  -d "config.cookie_names[]=jwt_token"  # 支持Cookie傳遞token

也可只為特定服務啓用:

# 只為支付服務啓用JWT
curl -X POST http://localhost:8001/services/payment-service/plugins \
  -d "name=jwt"

2. 創建消費者與憑證

添加一個消費者(客户端)並生成JWT憑證:

# 創建消費者
curl -X POST http://localhost:8001/consumers \
  -d "username=mobile-app"

# 為消費者生成JWT憑證
curl -X POST http://localhost:8001/consumers/mobile-app/jwt \
  -d "algorithm=HS256"

返回結果包含token,客户端請求時需在Header中攜帶:

curl http://localhost:8000/api/user \
  -H "Authorization: Bearer <生成的token>"

未攜帶有效token的請求會被攔截,返回401狀態碼。

五、最佳實踐與避坑指南

  1. 路由設計規範:按業務域劃分路由(如/api/user/api/order),避免過細或過粗。路徑中可包含版本(如/api/v1/user),便於平滑升級。
  2. 插件粒度控制:全局插件(如基礎認證)作用於所有服務,服務級插件(如訂單服務限流)針對特定服務,路由級插件(如登錄接口限流)用於更精細的控制。
  3. 集羣部署注意:單節點Kong的限流插件用local策略,集羣環境需改用redis策略,確保限流計數在節點間同步。
  4. 監控與日誌:啓用prometheus插件暴露監控指標,結合file-log插件記錄請求日誌:
# 啓用Prometheus監控
curl -X POST http://localhost:8001/plugins \
  -d "name=prometheus"

# 啓用日誌插件
curl -X POST http://localhost:8001/plugins \
  -d "name=file-log" \
  -d "config.path=/var/log/kong/access.log"
  1. 避免性能瓶頸:Kong本身性能優異,但過多插件會增加開銷。建議只保留必要插件,複雜邏輯通過自定義插件異步處理。

總結

Kong網關通過Service、Route和Plugin的組合,輕鬆實現了微服務的路由轉發、流量控制和認證安全。它的優勢在於輕量高性能(基於Nginx)和靈活的插件機制,能適應從簡單到複雜的各種場景。

實際使用中,重點在於合理設計路由規則和插件策略:路由要清晰易維護,插件要按需啓用避免性能損耗。無論是中小團隊的快速部署,還是大型集羣的高可用需求,Kong都能提供可靠的網關解決方案,讓業務服務專注於核心邏輯,無需重複處理橫切關注點。