API 网关是微服务架构的流量入口与治理中枢。面对 Kong、Envoy、Traefik 三条技术路径,团队常陷入"功能相似、生态重叠、指标不透明"的选型困境。本文从架构原理、14 维度横向对比、三大网关深度实战三个层面,系统梳理 API 网关的技术全景,并给出可直接落地的生产配置。
一、API 网关职责模型
1.1 南北流量 vs 东西流量
API 网关的核心职责是流量控制,但不同维度的流量对应不同的网关形态:
- 南北流量(North-South Traffic):客户端到集群的入站流量。典型网关承担路由转发、认证鉴权、TLS 卸载、限流熔断等职责,代表产品为 Kong、Traefik、Nginx。
- 东西流量(East-West Traffic):集群内部服务间的通信流量。这一场景由 Service Mesh 接管,典型产品为 Istio、Linkerd,其数据面通常也基于 Envoy Proxy。
注意边界模糊化趋势:Envoy 既可以是 API 网关(南北向),也可以是 Service Mesh 数据面(东西向);Istio Ingress Gateway 本质上是披着网关外衣的 Envoy Sidecar 集合。
1.2 核心功能矩阵
| 能力 | 职责说明 | 关键技术点 |
|---|---|---|
| 路由 | 将请求按规则分发至后端服务 | 路径匹配、Host 匹配、Header 匹配、权重分流 |
| 负载均衡 | 在多个后端实例间分配流量 | Round Robin、Least Conn、Consistent Hash |
| 限流 | 控制单位时间内的请求量,防止雪崩 | 令牌桶、漏桶、滑动窗口 |
| 熔断 | 在下游故障时快速失败,避免级联崩溃 | 错误率阈值、慢请求阈值、半开探测 |
| 认证 | 验证请求者身份与权限 | JWT、OAuth2、mTLS、API Key |
| 日志与可观测性 | 记录请求全链路并输出指标 | Access Log、Prometheus Metrics、OpenTelemetry Tracing |
| 协议转换 | 在客户端与服务间转换协议 | HTTP ↔ gRPC、REST ↔ GraphQL、WebSocket 代理 |
二、三大网关选型总表(14 维度对比)
| 维度 | Kong | Envoy | Traefik |
|---|---|---|---|
| 核心引擎 | OpenResty(Nginx + LuaJIT) | C++ 自研(事件驱动) | Go 自研(标准库 net/http) |
| 配置方式 | Admin API / Declarative Config / DB | xDS API(LDS/RDS/CDS/EDS) | 动态配置发现(Docker/K8s 标签等) |
| 存储依赖 | PostgreSQL/Cassandra(或 DB-less) | 无(全内存,依赖控制面) | 无(纯文件/标签驱动) |
| 插件机制 | Lua 插件 / Go Plugin Server | C++ Filter / Wasm 扩展 | Go 中间件链 |
| 性能 | 极高(近原生 Nginx) | 极高(C++ 零拷贝,低延迟) | 高(Go 调度器 overhead 略高) |
| K8s 集成 | Kong Ingress Controller | Istio Ingress Gateway / Gateway API | 原生 Ingress / IngressRoute / Gateway API |
| 动态配置 | 热重载(DB-less 模式毫秒级) | xDS 增量推送(亚秒级) | 自动监听变更(秒级) |
| GraphQL 支持 | GraphQL 插件(解析查询、缓存) | Envoy GraphQL Filter(查询执行) | 需借助中间件或外部服务 |
| 服务发现 | Consul / DNS / K8s / Eureka | 原生支持所有主流发现机制 | Docker / K8s / Consul / Marathon |
| 可观测性 | Prometheus / Datadog / OTel | 原生 Stats / OTel / Envoy ALS | 原生 Prometheus / Jaeger / Zipkin |
| TLS 管理 | 手动配置 / ACME(需插件) | SDS 动态证书 / Istio 自动管理 | Let’s Encrypt 全自动 ACME |
| 学习曲线 | 中等(Lua 插件需学习) | 陡峭(xDS 模型复杂) | 平缓(文档友好,配置简洁) |
| 社区与生态 | 极活跃(Kong Inc 商业支撑) | CNCF 毕业项目(Istio 默认数据面) | CNCF 沙箱项目(云原生原生设计) |
| 典型场景 | 大型 API 平台、企业级网关 | Service Mesh、混合云、高性能代理 | 云原生 K8s 集群、中小规模微服务 |
三、Kong 深度实战
3.1 OpenResty 架构解读
Kong 基于 OpenResty 构建,相当于在 Nginx 事件循环中嵌入了 LuaJIT 运行时。核心架构分为三层:
- Nginx 核心层:处理连接、SSL 握手、事件循环。
- OpenResty 层:通过
ngx_lua模块暴露 Lua API,支持在 Nginx 各阶段(init、access、content、log等)注入逻辑。 - Kong 框架层:封装了路由匹配、插件执行链、Admin API、数据存储抽象。
Kong 的插件在 Nginx 的 access 阶段串联执行,每个请求会按全局/服务/路由三级作用域依次触发插件钩子。
3.2 部署模式:DB 模式 vs DB-less
- Traditional Mode:Admin API 将配置写入 PostgreSQL 或 Cassandra,Kong 节点从数据库加载配置。适合需要动态变更的大型集群。
- DB-less Mode:通过
declarative_config文件全量加载配置,重启即生效。适合 GitOps 工作流、K8s ConfigMap 管理。
DB-less 配置示例:
_format_version: "3.0"
services:
- name: user-service
url: http://user-api:8080
routes:
- name: user-routes
paths: [/api/v1/users]
plugins:
- name: rate-limiting
config:
minute: 100
policy: redis
redis_host: redis
- name: jwt
consumers:
- username: mobile-app
jwt_secrets:
- key: mobile-issuer
secret: "your-256-bit-secret"
启动命令:
export KONG_DATABASE=off
export KONG_DECLARATIVE_CONFIG=/path/to/kong.yml
kong start
3.3 Admin API 核心操作
# 创建服务
curl -X POST http://localhost:8001/services \
--data name=order-service \
--data url=http://order-api:8080
# 添加路由
curl -X POST http://localhost:8001/services/order-service/routes \
--data 'paths[]=/api/v1/orders'
# 启用 Redis 限流(全局)
curl -X POST http://localhost:8001/plugins \
--data name=rate-limiting \
--data config.minute=200 \
--data config.policy=redis \
--data config.redis_host=redis
# 启用 JWT
curl -X POST http://localhost:8001/plugins --data name=jwt
# 为消费者创建 JWT Credentials
curl -X POST http://localhost:8001/consumers/web-app/jwt \
--data key=web-issuer \
--data secret="super-secret-key"
Admin API 默认无内置认证,生产环境应通过防火墙、mTLS 或 Kong Manager 代理限制访问。
3.4 常用插件详解
Rate Limiting(限流)
plugins:
- name: rate-limiting
config:
minute: 120
hour: 3000
policy: redis
redis_host: redis
redis_timeout: 2000
fault_tolerant: true # Redis 故障时不过度拒绝
fault_tolerant: true 是生产必选项:当 Redis 不可用时,Kong 允许流量通过并记录错误,避免网关自身成为故障源。
Key Auth
curl -X POST http://localhost:8001/plugins \
--data name=key-auth \
--data config.key_names=apikey \
--data config.hide_credentials=true
curl -X POST http://localhost:8001/consumers/mobile-app/key-auth \
--data key=ak_prod_2026_xyz789
Request Transformer
plugins:
- name: request-transformer
config:
add:
headers: ["X-Request-ID:$(request_id)"]
remove:
headers: [X-Internal-Token]
OAuth2
curl -X POST http://localhost:8001/plugins \
--data name=oauth2 \
--data config.scopes=read,write \
--data config.mandatory_scope=true \
--data config.enable_authorization_code=true
curl -X POST http://localhost:8001/consumers/partner-app/oauth2 \
--data name="Partner Portal" \
--data client_id=partner_client_001 \
--data redirect_uris[]="https://partner.example.com/callback"
3.5 Go Plugin Server 开发自定义插件
Kong 3.x 支持通过 PDK 以 Go 语言编写外部插件,由 go-pluginserver 进程管理:
package main
import (
"github.com/Kong/go-pdk"
"github.com/Kong/go-pdk/server"
)
type CustomAuthConfig struct {
HeaderName string `json:"header_name"`
Secret string `json:"secret"`
}
type CustomAuth struct{ Config CustomAuthConfig }
func New() interface{} { return &CustomAuth{} }
func (conf *CustomAuth) Access(kong *pdk.PDK) error {
header, err := kong.Request.GetHeader(conf.Config.HeaderName)
if err != nil || header != conf.Config.Secret {
kong.Response.Exit(401, `{"error":"unauthorized"}`, nil)
return nil
}
kong.ServiceRequest.SetHeader("X-Auth-Verified", "true")
return nil
}
func main() {
server.StartServer(New, "0.1.0", 1)
}
Go 插件运行在独立进程,与 Kong Worker 通过 Unix Socket 通信,延迟比原生 Lua 插件略高(约 0.5-2ms),但适合对接企业内部的复杂认证体系。
四、Envoy 深度实战
4.1 xDS API:动态配置核心
Envoy 的架构设计与 Kong/Traefik 截然不同:所有配置均通过控制面动态推送。控制面通过四种 xDS 协议向 Envoy 下发配置:
| xDS 类型 | 全称 | 配置内容 |
|---|---|---|
| LDS | Listener Discovery Service | 监听端口、TLS 上下文、Filter 链 |
| RDS | Route Discovery Service | 路由规则(Virtual Host → Cluster 映射) |
| CDS | Cluster Discovery Service | 上游服务集群定义、负载均衡策略、健康检查 |
| EDS | Endpoint Discovery Service | 集群后端实例的 IP/端口列表 |
此外还有 SDS(Secret Discovery Service)动态推送 TLS 证书,ADS(Aggregated Discovery Service)统一流式推送全部配置,避免配置不一致窗口。
4.2 静态配置示例
虽然 Envoy 主打动态 xDS,理解其静态配置模型是掌握 Filter 链的基础:
static_resources:
listeners:
- name: http_listener
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
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
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match: { prefix: "/api/v1/users" }
route:
cluster: user_service
retry_policy:
retry_on: "gateway-error,connect-failure"
num_retries: 3
per_try_timeout: 5s
http_filters:
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(request_handle)
request_handle:headers():add("X-Envoy-Lua", "injected")
end
- name: envoy.filters.http.router
clusters:
- name: user_service
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
health_checks:
- timeout: 5s
interval: 10s
unhealthy_threshold: 3
healthy_threshold: 2
http_health_check: { path: "/healthz" }
load_assignment:
cluster_name: user_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: user-api, port_value: 8080 }
- name: order_service
connect_timeout: 5s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 1000
max_pending_requests: 1000
max_requests: 1000
max_retries: 3
load_assignment:
cluster_name: order_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: order-api, port_value: 8080 }
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
设计要点:
- Filter 链有序执行:
luaFilter 在router之前,可修改请求;响应阶段按逆序执行。 - Circuit Breakers 基于集群:每个 Cluster 独立统计错误率/连接数,触发熔断后返回
503。 - Retry Budget 优于固定重试:基于实时请求量动态计算可重试比例,避免重试风暴。
4.3 与 Istio 集成
在 Istio 架构中,Envoy 作为 Sidecar 注入每个 Pod。Istiod 将 Kubernetes Service/VirtualService/DestinationRule 翻译为 xDS 配置,通过 ADS 推送:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service-vs
spec:
hosts:
- user-service
http:
- match:
- uri:
prefix: /api/v1/users
route:
- destination:
host: user-service
subset: v1
weight: 90
- destination:
host: user-service
subset: v2
weight: 10
retries:
attempts: 3
perTryTimeout: 5s
retryOn: gateway-error,connect-failure
timeout: 15s
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service-dr
spec:
host: user-service
trafficPolicy:
outlierDetection:
consecutiveErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
subsets:
- name: v1
labels: { version: v1 }
- name: v2
labels: { version: v2 }
Istio 的 outlierDetection 对应 Envoy 的异常点驱逐机制:连续 5 次错误即驱逐实例,30 秒基底时间逐次退避。
4.4 Wasm 扩展
Envoy 通过 Proxy-Wasm 规范支持用 Rust、C++、Go(TinyGo)编写 Filter,无需重新编译 Envoy:
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
#[no_mangle]
pub fn _start() {
proxy_wasm::set_log_level(LogLevel::Debug);
proxy_wasm::set_http_context(|_, _| -> Box<dyn HttpContext> {
Box::new(CustomFilter)
});
}
struct CustomFilter;
impl Context for CustomFilter {}
impl HttpContext for CustomFilter {
fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
if let Some(token) = self.get_http_request_header("authorization") {
if !token.starts_with("Bearer ") {
self.send_http_response(401, vec![], Some(b"Unauthorized"));
return Action::Pause;
}
}
Action::Continue
}
}
编译为 Wasm 模块后通过 Envoy Filter 配置加载。单次执行开销约 0.1-0.5ms,适合轻量级认证、日志增强等场景;重型计算建议下沉至独立服务。
4.5 Envoy GraphQL Filter
Envoy 1.26+ 提供原生 GraphQL Filter,可在网关层解析查询、执行缓存、限制复杂度:
http_filters:
- name: envoy.filters.http.graphql
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.graphql.v3.GraphQL
schema:
inline_string: |
type Query { user(id: ID!): User }
type User { id: ID! name: String! email: String! }
execution:
max_depth: 5
max_cost: 1000
enable_introspection: false
Envoy 的 GraphQL 支持仍处于发展阶段,复杂查询重写、批量请求(DataLoader 模式)建议由 Apollo Router 或自建聚合层处理。
五、Traefik 深度实战
5.1 动态配置发现机制
Traefik 的设计理念是约定优于配置:启动后自动监听各类服务发现源,实时生成路由与中间件。
支持的 Provider:Docker(容器标签)、Kubernetes Ingress/IngressRoute/Gateway API(监听 K8s API Server)、Consul Catalog/KV、File(本地 TOML/YAML)等。
5.2 Docker 标签路由示例
services:
traefik:
image: traefik:v3.1
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
- --entrypoints.web.http.redirections.entryPoint.to=websecure
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
user-api:
image: user-api:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.user-api.rule=Host(`api.example.com`) && PathPrefix(`/api/v1/users`)"
- "traefik.http.routers.user-api.entrypoints=websecure"
- "traefik.http.routers.user-api.tls.certresolver=letsencrypt"
- "traefik.http.services.user-api.loadbalancer.server.port=8080"
- "traefik.http.middlewares.user-ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.user-ratelimit.ratelimit.burst=200"
- "traefik.http.routers.user-api.middlewares=user-ratelimit"
仅需容器标签,无需任何静态配置文件。Traefik 监听 Docker Socket,新容器启动即刻生效。
5.3 K8s IngressRoute CRD
Traefik 的 IngressRoute CRD 支持比原生 Ingress 更丰富的路由语法与中间件链:
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-gateway
namespace: production
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/api/v1/users`)
kind: Rule
services:
- name: user-service
port: 8080
healthCheck:
path: /healthz
interval: 10s
middlewares:
- name: jwt-auth
- name: rate-limit-100
- match: Host(`api.example.com`) && PathPrefix(`/api/v1/orders`)
kind: Rule
services:
- name: order-service
port: 8080
middlewares:
- name: circuit-breaker-default
tls:
certResolver: letsencrypt
5.4 中间件链详解
Traefik 的中间件按声明顺序正序执行(请求阶段),响应阶段逆序执行。
RateLimit
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit-100
spec:
rateLimit:
average: 100
burst: 200
period: 1m
sourceCriterion:
ipStrategy:
depth: 1
CircuitBreaker
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: circuit-breaker-default
spec:
circuitBreaker:
expression: |
LatencyAtQuantileMS(50.0) > 100 ||
ResponseCodeRatio(500, 600, 0, 600) > 0.25 ||
NetworkErrorRatio() > 0.5
Traefik 的熔断表达式支持延迟分位数、错误码比例、网络错误比例三种指标的组合判断,比固定阈值更灵活。
5.5 Let’s Encrypt 自动 TLS
Traefik 的 ACME 集成是三大网关中最简洁的:一行 --certificatesresolvers 参数即可开启自动证书申请与续期,支持 HTTP Challenge、TLS-ALPN-01 Challenge 和 DNS Challenge(Wildcard 证书)。
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /letsencrypt/acme.json
tlsChallenge: {}
5.6 Dashboard 与可观测性
api:
dashboard: true
insecure: false
metrics:
prometheus:
addEntryPointsLabels: true
addServicesLabels: true
addRoutersLabels: true
buckets: [0.1, 0.3, 1.2, 5.0]
Traefik Dashboard 实时展示 Routers、Services、Middlewares 状态及健康检查结果,是排查路由未生效的第一工具。
六、网关层 GraphQL 支持
GraphQL 网关层的核心诉求有三:查询路由、字段级缓存、N+1 防护。
| 方案 | 架构 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|---|
| Apollo Router | Rust 核心 + Rhai/Yaml 配置 | 极速、原生 Federation、Telemetry 完备 | 学习曲线中等、商业功能付费 | 大型 GraphQL 联邦平台 |
| Kong GraphQL Plugin | OpenResty Lua 插件 | 与 Kong 生态无缝集成、轻量 | 仅基础查询缓存、无联邦支持 | 已有 Kong 基础设施的混合 API 平台 |
| 自建聚合层 | 自定义服务 + DataLoader | 灵活、业务定制 | 维护成本高、性能需调优 | 特定业务逻辑紧密耦合的场景 |
Apollo Router 部署示例
supergraph:
listen: 0.0.0.0:4000
introspection: false
telemetry:
exporters:
metrics:
prometheus:
enabled: true
listen: 0.0.0.0:9090
tracing:
otlp:
endpoint: http://jaeger:4317
plugins:
experimental.limit:
max_depth: 10
max_height: 100
max_aliases: 15
max_root_fields: 5
cors:
origins: ["https://app.example.com"]
allow_credentials: true
Apollo Router 的 experimental.limit 插件限制查询深度、高度、别名数与根字段数,是比简单超时更有效的 DoS 防护手段。
七、限流算法对比与各网关实现
7.1 三大算法原理
| 算法 | 机制 | 突刺容忍度 | 平滑度 |
|---|---|---|---|
| 令牌桶 | 固定速率放入令牌,请求消耗令牌 | 允许突发(桶容量决定) | 中等 |
| 漏桶 | 请求进入漏桶,固定速率漏出处理 | 严格平滑,无突发 | 最高 |
| 滑动窗口 | 统计最近时间窗口内的请求数 | 精确无突刺 | 高 |
7.2 各网关限流实现
Kong:Redis 策略本质采用令牌桶算法(配置 minute: 100 即每分钟发放 100 个令牌)。支持 fault_tolerant:Redis 故障时降级放行。
Envoy:
- Local Rate Limit:单实例内存限流,基于令牌桶。
- Global Rate Limit:通过 gRPC 调用外部 RLS(如 Lyft 开源的
ratelimit),支持滑动窗口与自定义 Descriptor。
http_filters:
- name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
stat_prefix: http_local_rate_limiter
token_bucket:
max_tokens: 1000
tokens_per_fill: 100
fill_interval: 1s
Traefik:中间件 rateLimit 基于令牌桶算法(average 为填充速率,burst 为桶容量)。支持按源 IP 或请求头分组限流。
八、一句话总结
- Kong:企业级 API 管理首选,OpenResty 性能卓越,插件生态丰富,适合精细认证、复杂转换、DB 无状态部署的大型平台。
- Envoy:云原生基础设施基石,xDS 动态配置与 Wasm 扩展使其在 Service Mesh、多集群混合云场景中无出其右。
- Traefik:云原生 K8s 集群的轻量入口,自动发现与 Let’s Encrypt 零配置 TLS 让中小团队在分钟级完成网关部署。
若团队已深度使用 Kubernetes 且追求极简运维 → Traefik;若需构建企业级 API 管理平台 → Kong;若处于 Istio Service Mesh 生态或追求极致性能与多语言扩展 → Envoy。
FAQ
Q1:Kong DB-less 模式下如何实现配置热更新?
A:DB-less 模式不支持增量热更新,需全量替换 kong.yml 并触发 kong reload。建议配合 K8s ConfigMap + Sidecar 监听文件变更,或使用 Kong Ingress Controller。
Q2:Envoy 的 Wasm Filter 性能损耗如何?
A:单次执行开销约 0.1-0.5ms,C++ SDK 最低,Rust 次之,TinyGo 略高。建议用于轻量级逻辑(认证标注入、Header 修改),避免在 Wasm 中做 JSON 解析或复杂计算。
Q3:Traefik 的 CircuitBreaker 与 Envoy 的 OutlierDetection 有何区别?
A:Traefik CircuitBreaker 在网关层统计请求错误率/延迟,触发后直接拒绝流量;Envoy OutlierDetection 在集群层驱逐异常后端 Endpoint,由负载均衡器将流量导向健康实例。两者互补,可叠加使用。
Q4:是否需要在 API 网关前再挂一层 CDN?
A:公网流量强烈建议。CDN 承担 DDoS 清洗、边缘缓存、TLS 终止、地理位置路由,将网关从基础网络攻击中解放出来,专注业务级治理。
Q5:三大网关能否混合部署?
A:可以。常见分层架构:CDN → Kong/Traefik(L7 入口网关,负责认证、限流)→ Envoy(Service Mesh 边车,负责东西向负载均衡、熔断)→ 业务服务。此模式兼顾了各产品的能力边界。
相关阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。