Language:Chinese VersionEnglish Version

您的 API 网关可能正在过度设计一个简单问题

API 网关承诺提供集中式身份验证、限流、路由、可观测性和协议转换。实际上,它们也是最常过度配置的基础设施组件之一——为一个每秒处理 200 个请求的应用程序部署完整的 Kong 或 Envoy,就像用货运电梯来移动一个手提箱一样。本指南介绍了 API 网关的实际功能、何时需要使用 API 网关、何时简单的反向代理就足够了,以及主要选项(Kong、Envoy、Traefik)的适用场景。

API 网关的实际功能

API 网关位于您的服务之前,处理那些原本需要在每个服务中实现的横切关注点:

  • 身份验证和授权:在请求到达您的服务之前验证 JWT 令牌、API 密钥、OAuth 流程
  • 限流:按用户、按 IP 或按密钥的请求限制
  • 请求路由:将 /v1/users 路由到用户服务,将 /v1/orders 路由到订单服务
  • 协议转换:REST 到 gRPC、REST 到 GraphQL 的聚合
  • 可观测性:集中式访问日志、指标、分布式跟踪启动
  • 请求/响应转换:添加标头、转换负载、聚合响应
  • SSL 终止:在一个地方处理 TLS,而不是每个服务都处理

您真的需要 API 网关吗?

在评估工具之前,先问问自己是否真的需要 API 网关。如果您符合以下情况,可能不需要:

  • 您的后端服务少于 5 个
  • 您正在运行一个具有单一部署的单体应用
  • 您的身份验证完全在应用程序内部处理
  • 您没有向第三方开发者公开公共 API

您可能真正需要的是:一个配置良好的反向代理(Nginx 或 Caddy)加上应用级中间件。

# Nginx 作为三服务应用的简单"网关"
# 这处理了小型团队从 API 网关所需的 80% 功能

upstream user_service {
    server user-service:8001;
    keepalive 32;
}
upstream order_service {
    server order-service:8002;
    keepalive 32;
}
upstream payment_service {
    server payment-service:8003;
    keepalive 32;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    # 限流(简单,内置在 Nginx 中)
    limit_req_zone $binary_remote_addr zone=api:10m rate=100r/m;
    limit_req zone=api burst=20 nodelay;

    # 按路径前缀路由
    location /v1/users/ {
        proxy_pass http://user_service/;
        proxy_set_header X-Request-ID $request_id;
        proxy_set_header Authorization $http_authorization;
    }

    location /v1/orders/ {
        proxy_pass http://order_service/;
        proxy_set_header X-Request-ID $request_id;
    }

    location /v1/payments/ {
        # 支付端点的额外限流
        limit_req zone=api burst=5 nodelay;
        proxy_pass http://payment_service/;
    }
}

这处理了路由、限流、请求 ID 传播和 SSL 终止,无需任何额外的依赖。

Kong:满足复杂需求的可扩展网关

Kong 是最广泛部署的开源 API 网关。它基于 Nginx/OpenResty 构建,在其上添加了插件系统、管理 API 和声明式配置。

# Kong 声明式配置 (kong.yml) — 在无数据库模式下部署 Kong
_format_version: "3.0"

services:
  - name: user-service
    url: http://user-service:8001
    plugins:
      - name: jwt
        config:
          key_claim_name: kid
          secret_is_base64: false
      - name: rate-limiting
        config:
          minute: 1000
          hour: 10000
          policy: local
    routes:
      - name: user-routes
        paths:
          - /v1/users
        strip_path: false

  - name: payment-service
    url: http://payment-service:8003
    plugins:
      - name: jwt
      - name: rate-limiting
        config:
          minute: 100   # 支付限制更严格
          policy: redis  # 通过 Redis 实现分布式限流
          redis_host: redis
    routes:
      - name: payment-routes
        paths:
          - /v1/payments

plugins:
  - name: correlation-id     # 为所有请求添加 X-Correlation-ID
    config:
      header_name: X-Request-ID
      generator: uuid
  - name: prometheus          # 暴露 /metrics 端点
  - name: file-log
    config:
      path: /dev/stdout
      reopen: false
# 无数据库模式下的 Kong docker-compose.yml
services:
  kong:
    image: kong:3.6
    environment:
      KONG_DATABASE: "off"
      KONG_DECLARATIVE_CONFIG: /kong/declarative/kong.yml
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
      KONG_ADMIN_LISTEN: "0.0.0.0:8001"
    ports:
      - "80:8000"
      - "443:8443"
      - "8001:8001"   # 管理 API — 请勿公开暴露
    volumes:
      - ./kong.yml:/kong/declarative/kong.yml

何时选择 Kong

  • 为外部 API 消费者提供开发者门户
  • 复杂的身份验证流程(OAuth、多个 JWT 签发者)
  • 按消费者限流(不同 API 密钥层级设置不同限制)
  • 丰富的插件生态系统(LDAP、AWS Lambda、GraphQL、金丝雀部署)
  • 需要 GUI 管理界面的团队

Envoy: 服务网格的代理

Envoy 是一个 Lyft 最初构建的第 7 层代理。它是 Istio 的数据平面,也是大多数 Kubernetes 服务网格的核心。与 Kong(设计为入口/边缘网关)不同,Envoy 设计为作为边车代理在每个服务实例旁边运行。

# envoy.yaml — 前置代理配置
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
                access_log:
                  - name: envoy.access_loggers.stdout
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
                http_filters:
                  - name: envoy.filters.http.jwt_authn
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
                      providers:
                        myapp_jwt:
                          issuer: "https://auth.example.com"
                          remote_jwks:
                            http_uri:
                              uri: "https://auth.example.com/.well-known/jwks.json"
                              cluster: auth_cluster
                              timeout: 5s
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: services
                      domains: ["*"]
                      routes:
                        - match:
                            prefix: "/v1/users"
                          route:
                            cluster: user_service
                        - match:
                            prefix: "/v1/orders"
                          route:
                            cluster: order_service

何时使用 Envoy

  • 在 Kubernetes 中运行且需要服务网格
  • 需要高级流量管理(内置断路器、重试、异常检测)
  • gRPC 优先架构(Envoy 拥有一流 gRPC 支持)
  • 平台团队构建内部基础设施产品

何时 Envoy 过于复杂

Envoy 的配置以其冗长和复杂而闻名。在 3 个服务的应用程序上运行 Istio 会带来显著的操作开销——每个 Pod 都需要 Envoy sidecar、控制平面组件和证书管理。许多团队为了符合 Kubernetes”最佳实践”而采用它,结果花在调试服务网格上的时间比调试实际应用程序还要多。

Traefik:开发者友好的中间选择

Traefik 专为容器环境而设计。它能自动发现 Docker 和 Kubernetes 服务,并根据标签/注释进行自我配置,无需手动路由配置:

# 使用 Traefik 自动发现的 docker-compose.yml
services:
  traefik:
    image: traefik:v3.0
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./letsencrypt:/letsencrypt

  user-service:
    image: myapp/user-service
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.users.rule=PathPrefix(`/v1/users`)"
      - "traefik.http.routers.users.entrypoints=websecure"
      - "traefik.http.routers.users.tls.certresolver=letsencrypt"
      - "traefik.http.middlewares.users-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.users-ratelimit.ratelimit.burst=50"
      - "traefik.http.routers.users.middlewares=users-ratelimit"

决策矩阵

根据您的具体情况选择合适的工具:

  • 单体应用或 2-3 个服务,无公共 API:Nginx 或 Caddy 反向代理。无需 API 网关。
  • Docker Compose、小型微服务、重视开发者体验:Traefik。自动发现是真正的生产力提升。
  • 公共开发者 API、复杂认证、分层限流:Kong。其插件生态系统和管理界面值得选择。
  • Kubernetes、服务网格、平台工程团队:Envoy/Istio 或 Cilium 服务网格。
  • 托管云服务:如果您已经在这些平台上,可选择 AWS API Gateway、GCP API Gateway 或 Cloudflare API Shield。

关键洞察:API 网关是您必须操作、监控、调试和升级的基础设施。选择满足您实际需求的最简单选项,而不是功能最多的那个。

By Michael Sun

Founder and Editor-in-Chief of NovVista. Software engineer with hands-on experience in cloud infrastructure, full-stack development, and DevOps. Writes about AI tools, developer workflows, server architecture, and the practical side of technology. Based in China.

Leave a Reply

Your email address will not be published. Required fields are marked *

You missed