您的 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 网关是您必须操作、监控、调试和升级的基础设施。选择满足您实际需求的最简单选项,而不是功能最多的那个。
