反向代理与 API 网关:Nginx/Kong/Envoy 实践

深入讲解反向代理与 API 网关的核心职责,涵盖 Nginx 配置实战(upstream、健康检查、限流)、Kong 与 Envoy 网关能力对比、熔断重试鉴权等流量治理,以及 WebSocket 与 gRPC 代理与选型决策。

反向代理与 API 网关是微服务架构的流量中枢:客户端只与一个入口打交道,真正的业务集群躲在代理之后。从最简单的 Nginx 到云原生时代的 Kong、Envoy,理解这一层的能力边界与取舍,是后端架构师的必修课。

一、反向代理核心职责

1.1 正向代理与反向代理

正向代理(代理客户端,翻墙/抓包场景):
客户端 A ─┐
客户端 B ─┼─→ 正向代理 ─→ 目标服务器
客户端 C ─┘      ↑
           代表客户端发起请求

反向代理(代理服务端,业务入口场景):
客户端 ─→ 反向代理(统一入口 80/443)
              ├─→ 后端节点 1
              ├─→ 后端节点 2
              └─→ 后端节点 3
           代表服务端对外提供服务

一句话:正向代理隐藏客户端,反向代理隐藏服务端。

1.2 反向代理承担的工作

职责说明典型实现
请求转发按规则分发到后端节点proxy_pass / upstream
负载均衡轮询、加权、哈希等Nginx 内置策略
TLS 终止统一卸载 HTTPS,后端走明文证书挂在代理层
健康检查摘除故障节点主动探测 / 被动失败计数
缓存静态资源与响应缓存proxy_cache
安全防护限流、IP 黑名单、WAFlimit_req / 第三方模块
协议转换WebSocket 升级、gRPC 透传http1.1 upgrade / grpc_pass

二、Nginx 配置实战

2.1 upstream 与转发

# 全局 http 块
http {
    # 动态上游:按权重负载均衡 + 被动健康检查
    upstream backend_api {
        server 192.168.1.11:8080 weight=5 max_fails=3 fail_timeout=30s;
        server 192.168.1.12:8080 weight=3 max_fails=3 fail_timeout=30s;
        server 192.168.1.13:8080 backup;          # 冷备节点

        keepalive 32;                              # 与后端的长连接池
        keepalive_timeout 60s;
    }

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

        location /api/ {
            proxy_pass http://backend_api;
            proxy_http_version 1.1;
            proxy_set_header Connection "";

            # 透传关键头
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            # 超时控制
            proxy_connect_timeout 5s;
            proxy_read_timeout 30s;
            proxy_send_timeout 30s;
        }
    }
}

2.2 主动健康检查(商业版/openresty 特性)

开源 Nginx 被动健康检查依赖请求失败计数,主动健康检查可用 OpenResty + lua-resty-healthcheck 或第三方补丁:

# 简单请求级健康检查:给 /healthz 单独分组
upstream backend_api {
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
    zone upstream_backend 64k;   # 共享内存,配合 nginx-plus/openresty
}

server {
    location = /healthz {
        # 该请求专门用于健康探测
        access_log off;
        proxy_pass http://backend_api;
        proxy_connect_timeout 2s;
        proxy_read_timeout 3s;
    }
}

2.3 限流配置

http {
    # 定义限流区域:1r/s 平均速率,突发 5
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=1r/s;

    # 定义并发连接限制
    limit_conn_zone $binary_remote_addr zone=per_ip_conn:10m;

    server {
        listen 80;

        location /api/ {
            # 漏桶限流,超过突发返回 503
            limit_req zone=api_limit burst=5 nodelay;
            limit_req_status 429;

            # 每 IP 最多 20 并发
            limit_conn per_ip_conn 20;
            limit_conn_status 429;

            proxy_pass http://backend_api;
        }

        # 静态资源不限流
        location /static/ {
            alias /data/static/;
            expires 30d;
        }
    }
}

一句话:limit_req_zone 定义共享内存桶,burst 缓冲突发流量,nodelay 决定突发是否立即放行。

三、Kong 网关能力

3.1 架构模型

Kong 基于 Nginx + OpenResty + Lua,插件化地提供认证、限流、转换等能力,配置存储在后端数据库(PostgreSQL/Cassandra)中,支持声明式配置。

客户端 → Kong 网关(数据面,Nginx 内核)
            │  DB-less 模式:配置通过 Admin API 下发
            ├─→ 插件链:key-auth → rate-limiting → ...
            └─→ 上游服务(可多版本、加权)

Administrator → Admin API / declarative.yaml

3.2 声明式配置示例

# declarative.yaml(DB-less 模式)
_format_version: "2.1"
services:
  - name: order-service
    url: http://order-svc:8080
    routes:
      - name: order-route
        paths: ["/orders"]
        methods: ["GET", "POST"]
        strip_path: true
    plugins:
      - name: rate-limiting
        config:
          minute: 60
          hour: 3000
          policy: local
      - name: key-auth
        config:
          key_names: ["apikey"]
consumers:
  - username: partner-a
    keyauth_credentials:
      - key: secret-key-001

3.3 Kong 常用插件清单

类别插件作用
认证key-auth / jwt / oauth2 / basic-auth多种认证协议
安全ip-restriction / bot-detection / corsIP 白名单、反爬、跨域
流量rate-limiting / proxy-cache / request-transformer限流、缓存、改写
可观测prometheus / zipkin / file-log指标、链路、日志
转换response-transformer / correlation-id响应改写、注入链路 ID

四、Envoy 网关能力

4.1 核心抽象

Envoy 是 CNCF 孵化的高性能代理,面向 Service Mesh 设计,配置完全由 API 动态下发(xDS),支持 gRPC、HTTP/2、HTTP/3、HTTP/1.1 全栈协议。

# 最小 Envoy 静态配置(示例)
static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 10000 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                http_filters:
                  - name: envoy.filters.http.router
                route_config:
                  virtual_hosts:
                    - name: vh
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/api" }
                          route:
                            cluster: backend
  clusters:
    - name: backend
      connect_timeout: 5s
      type: STRICT_DNS
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: backend
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: backend, port_value: 8080 }

4.2 Envoy vs Kong vs Nginx

维度NginxKongEnvoy
内核原生 CNginx + OpenResty(Lua)C++
动态配置reloadAdmin API / DB-lessxDS 热更新
扩展方式模块(C)/ LuaLua 插件Lua/WASM Filter
协议支持HTTP/1.1、HTTP/2同 Nginx + 部分 gRPCHTTP/1.1/2/3、gRPC、Thrift
服务发现静态/DNS静态/DNS/ConsulEDS/xDS 原生
定位反向代理/负载均衡企业级 API 网关云原生数据面(网格)

一句话:Nginx 是「灵活的代理」,Kong 是「开箱即用的网关平台」,Envoy 是「为动态网格而生的数据面」。

五、网关层流量治理

5.1 熔断、重试与超时

流量治理三件套需要在网关统一配置,避免每个业务各自为政:

# Envoy route 上的治理配置
routes:
  - match: { prefix: "/api/order" }
    route:
      cluster: order_cluster
      timeout: 10s
      retry_policy:
        retry_on: "connect-failure,reset,5xx"
        num_retries: 3
        retry_host_predicate:
          - name: envoy.retry_host_predicates.previous_hosts
        per_try_timeout: 3s
circuit_breakers:
  thresholds:
    - priority: DEFAULT
      max_connections: 10000
      max_pending_requests: 5000
      max_requests: 10000
      max_retries: 3

5.2 网关层鉴权模式

模式一:网关统一鉴权(集中式)
客户端 → 网关(JWT 校验) → 后端(信任网关,跳过鉴权)
  优点:后端简单;缺点:网关成为安全焦点

模式二:网关透传,后端各自鉴权(分散式)
客户端 → 网关(透传 Token) → 每个服务自行校验
  优点:安全边界内聚;缺点:重复实现

模式三:集中鉴权服务 + 网关缓存
客户端 → 网关 → 鉴权服务(JWT/ACL) → 网关缓存结果 → 后端

5.3 JWT 网关校验示例(Kong jwt 插件 + Go)

// 网关层面校验 JWT 后,将解析出的用户信息以请求头透传给后端
package main

import (
    "fmt"
    "github.com/golang-jwt/jwt/v5"
)

// 校验并提取 claims(网关侧伪代码)
func verifyAndForward(token string) error {
    claims := jwt.MapClaims{}
    _, err := jwt.ParseWithClaims(token, claims, func(t *jwt.Token) (interface{}, error) {
        return []byte("gateway-secret"), nil
    })
    if err != nil {
        return fmt.Errorf("token invalid: %w", err)
    }
    // 通过 X-User-ID / X-User-Role 透传给下游
    // header.Set("X-User-ID", claims["sub"].(string))
    return nil
}

六、WebSocket 与 gRPC 代理

6.1 WebSocket 升级代理

WebSocket 靠 HTTP Upgrade 协议升级,代理必须放行 101 状态码与升级头:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

upstream ws_backend {
    server 192.168.1.21:9000;
    server 192.168.1.22:9000;
}

server {
    listen 80;
    location /ws/ {
        proxy_pass http://ws_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # 长连接超时:覆盖默认 60s,防止空闲被切断
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;

        # 支持粘性会话:同一连接固定到同一节点
        sticky cookie ws_route expires=1h;
    }
}

一句话:代理 WebSocket 的关键是透传 Upgrade/Connection 头并把读超时调大到小时级。

6.2 gRPC 代理

gRPC 是 HTTP/2 之上的二进制 RPC,代理层必须走 HTTP/2:

http {
    # gRPC 需要 HTTP/2 与 ssl
    server {
        listen 443 ssl http2;
        server_name grpc.example.com;

        ssl_certificate     /etc/nginx/tls/server.crt;
        ssl_certificate_key /etc/nginx/tls/server.key;

        # 监听 gRPC 端口(默认 50051 示例)
        location /helloworld.Greeter/ {
            grpc_pass grpc://grpc_backend;
        }
    }

    upstream grpc_backend {
        server 192.168.1.31:50051;
        server 192.168.1.32:50051;
    }
}

6.3 协议代理对比

协议代理要点常见问题
HTTP/1.1转发头、超时长连接被切断、头透传缺失
HTTP/2多路复用、连接复用需支持 h2c/h2 协商
WebSocket升级头、大超时、粘性超时误断、节点漂移
gRPCHTTP/2 + 流式语义需 HTTP/2、禁用 buffer 类改造
TCP/UDP (L4)四层透传、会话保持无法按 URL 路由

七、网关选型决策表

场景推荐方案理由
单体 + 静态资源入口Nginx轻量、稳定、配置简单
微服务 + 统一鉴权限流Kong插件生态成熟、管理界面友好
K8s + Service Mesh 规划Envoy/Istio云原生标准、动态下发
极高性能四层分发LVS/DPDK、Envoy L4用户态网络栈极致吞吐
混合协议(HTTP+gRPC+WS)Envoy / Nginx全协议原生支持
有团队维护 Lua/WASMKong / Envoy 二次开发深度定制需求

选型建议三步法:

  1. 先看协议需求:是否含 gRPC/HTTP/3、是否大量 WebSocket;
  2. 再看运维模式:静态配置可接受 vs 需要动态灰度;
  3. 最后看生态:团队是否已有 Nginx/OpenResty 经验、是否要进 Service Mesh。

八、总结

能力NginxKongEnvoy
反向代理★★★★★★★★★
API 网关功能★★★★★★★
动态配置★★★★★★★
云原生集成★★★★★★
学习/运维成本低中高

反向代理解决「流量怎么进」,API 网关解决「流量怎么管」。生产架构中常常两者共存:最外层用 Nginx/云负载均衡做 TLS 终止与静态加速,内层用 Kong/Envoy 做路由、鉴权、限流、灰度。无论选型如何,把健康检查、超时、熔断、重试、可观测这五项治理能力补齐,网关才能真正成为高可用架构的稳定基座。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「network」更多文章

  1. 云原生网络:CNI 容器网络、Overlay/Underlay 与 Service Mesh 数据面
  2. SSE 与实时通信方案:Server-Sent Events、WebSocket 对比与选型实战
  3. 网络故障排查实战:tcpdump/Wireshark/ss/iperf 工具链与分层诊断方法论