目录
- API Gateway 的核心定位
- 三大架构模式:Edge、Sidecar 与 Service Mesh Ingress
- Kong:OpenResty + Lua 插件生态
- Envoy:C++ 性能怪兽与 WASM 扩展
- Spring Cloud Gateway:Java 生态的贴身后卫
- KrakenD:超高速聚合网关
- 十维对比:选型一张表搞定
- 高级模式:聚合、BFF 与熔断
- 安全加固:OAuth2、API Key 与 WAF
- 性能调优实战
- Kubernetes 生产部署:Ingress + Helm
- FAQ
- 总结与选型建议
1. API Gateway 的核心定位
在微服务架构中,API Gateway 是流量的唯一入口,承担着以下职责:
- 路由转发:将外部请求按路径、Host、Header 路由到后端服务。
- 协议转换:HTTP/1.1 与 HTTP/2、gRPC、WebSocket 之间的协议桥接。
- 横切关注点:认证、鉴权、限流、熔断、日志、监控。
- 聚合与裁剪:将多个下游 API 聚合成一个端点,减少客户端连接数。
- 灰度与蓝绿:基于权重、Header、Cookie 实现流量切换。
API Gateway 不是简单的反向代理(如 Nginx),而是具有业务语义的智能路由层。它的设计直接影响系统的可用性、安全性和演进能力。
2. 三大架构模式:Edge、Sidecar 与 Service Mesh Ingress
2.1 Edge Gateway(边缘网关)
Edge Gateway 部署在集群边界,所有外部流量先经过它再进入内部服务。这是最经典的模式,代表产品包括 Kong、Nginx、AWS API Gateway、阿里云 API 网关。
架构特征:
- 单点入口,集中管理证书和防火墙规则。
- 客户端无感知后端拆分,网关内部完成路由。
- 适合南北向流量(North-South Traffic)。
优点:
- 运维简单,TLS 证书、WAF、DDoS 防护集中在边缘。
- 客户端只需记住一个域名。
缺点:
- 集中式意味着单点瓶颈,需要水平扩展和会话保持策略。
- 跨集群通信时,Edge Gateway 之间需要额外的联邦机制。
# 边缘网关架构示意(伪配置)
edge_gateway:
listeners:
- port: 443
tls: true
certificates:
- cert: /etc/ssl/certs/api.example.com.crt
key: /etc/ssl/private/api.example.com.key
routes:
- match:
path: /api/v1/users
backend:
service: user-service
port: 8080
- match:
path: /api/v1/orders
backend:
service: order-service
port: 8080
2.2 Sidecar Gateway(边车网关)
Sidecar Gateway 将网关能力下沉到每个服务实例旁边,通常与 Service Mesh(如 Istio、Linkerd)结合。Envoy 是最典型的 Sidecar 代理。
架构特征:
- 每个 Pod 或容器附带一个 Envoy Sidecar。
- 进出流量被 iptables 拦截,透明地经过 Sidecar。
- 适合东西向流量(East-West Traffic)的精细化治理。
优点:
- 去中心化,无单点故障。
- 可实现服务级别的细粒度熔断、重试、超时。
缺点:
- 资源开销增加,每个 Pod 多一个容器。
- 调试链路变长,需要掌握 Sidecar 日志和指标。
# Kubernetes Sidecar 注入示意
# Istio 通过 mutating webhook 自动注入 Envoy
apiVersion: v1
kind: Pod
metadata:
name: user-service-pod
annotations:
sidecar.istio.io/inject: "true"
spec:
containers:
- name: user-service
image: user-service:1.2.3
ports:
- containerPort: 8080
# 以下容器由 Istio 自动注入
- name: istio-proxy
image: istio/proxyv2:1.20.0
args:
- proxy
- sidecar
2.3 Service Mesh Ingress(服务网格入口网关)
Service Mesh Ingress 是 Edge Gateway 与 Sidecar 的混合体。Istio Gateway、Consul Ingress Gateway 属于此类。它们在网格边缘部署专用的 Envoy 实例,既具备 Edge Gateway 的入口能力,又享有 Service Mesh 的统一控制面。
架构特征:
- 入口流量先进入 Istio Gateway(Envoy),再分发到网格内的 Sidecar。
- 控制面(istiod)统一通过 xDS 协议推送路由规则。
- 支持 mTLS 全链路加密,无需应用改造。
优点:
- 统一的流量管理界面,南北向与东西向规则一致。
- 强大的可观测性(Envoy 原生生成 Prometheus、Jaeger 数据)。
缺点:
- 学习曲线陡峭,控制面故障会影响全集群。
- 小型团队可能过度设计。
# Istio Gateway + VirtualService 示例
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: public-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: api-tls-secret
hosts:
- "api.example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-route
spec:
hosts:
- "api.example.com"
gateways:
- public-gateway
http:
- match:
- uri:
prefix: /api/v1/users
route:
- destination:
host: user-service
port:
number: 8080
3. Kong:OpenResty + Lua 插件生态
3.1 架构概述
Kong 基于 OpenResty(Nginx + LuaJIT)构建,通过 Lua 插件扩展功能。其架构分为:
- 数据平面(DP):OpenResty 进程处理请求,加载路由和插件配置。
- 控制平面(CP):PostgreSQL 或 Cassandra 存储配置,Admin API 供外部管理。
Kong 3.x 引入了混合模式(Hybrid Mode):CP 和 DP 分离,DP 通过 gRPC 从 CP 同步配置,适合大规模集群。
3.2 核心组件关系
Client
-> Nginx Listener (OpenResty)
-> Lua Access Phase
-> Plugin Iterator (认证、限流、转换)
-> Lua Balancer Phase
-> Upstream Service
3.3 Declarative 配置示例(DB-less 模式)
Kong 支持无数据库模式,通过 kong.yml 声明式配置,适合容器化和 GitOps。
# kong.yml — Kong 声明式配置(DB-less 模式)
_format_version: "3.0"
# 定义上游服务
services:
- name: user-service
url: http://user-service:8080
# 路由匹配规则
routes:
- name: user-api-route
paths:
- /api/v1/users
methods:
- GET
- POST
strip_path: false
preserve_host: false
- name: order-service
url: http://order-service:8080
routes:
- name: order-api-route
paths:
- /api/v1/orders
methods:
- GET
# 全局插件配置
plugins:
# 速率限制:每分钟 100 次请求
- name: rate-limiting
config:
minute: 100
policy: local
fault_tolerant: true
hide_client_headers: false
# 作用范围:全局
# JWT 认证
- name: jwt
service: user-service
config:
uri_param_names: []
cookie_names: []
key_claim_name: iss
secret_is_base64: false
claims_to_verify:
- exp
# 跨域支持
- name: cors
config:
origins:
- "https://app.example.com"
methods:
- GET
- POST
- PUT
- DELETE
headers:
- Authorization
- Content-Type
max_age: 3600
credentials: true
# 消费者与凭证(模拟)
consumers:
- username: mobile-app
jwt_secrets:
- algorithm: HS256
key: mobile-app-key
secret: super-secret-key-do-not-share-in-production
3.4 自定义 Lua 插件示例
当内置插件无法满足需求时,可以编写自定义 Lua 插件。
-- plugins/custom-header-handler.lua
-- 自定义插件:为响应添加追踪头
local CustomHeaderHandler = {
VERSION = "1.0.0",
PRIORITY = 1000, -- 插件执行优先级,数字越大越早执行
}
-- 在 Access 阶段执行
function CustomHeaderHandler:access(conf)
-- 从请求头中提取追踪 ID,若不存在则生成
local trace_id = kong.request.get_header("X-Request-ID")
if not trace_id or trace_id == "" then
trace_id = kong.request.get_id() -- 生成唯一 ID
kong.service.request.set_header("X-Request-ID", trace_id)
end
-- 将追踪 ID 存入上下文,供后续阶段使用
kong.ctx.shared.trace_id = trace_id
end
-- 在 Header Filter 阶段执行
function CustomHeaderHandler:header_filter(conf)
local trace_id = kong.ctx.shared.trace_id
if trace_id then
-- 在响应头中返回追踪 ID,方便客户端排查问题
kong.response.set_header("X-Trace-ID", trace_id)
end
-- 添加安全响应头
kong.response.set_header("X-Content-Type-Options", "nosniff")
kong.response.set_header("X-Frame-Options", "DENY")
end
return CustomHeaderHandler
3.5 Kong 的插件执行阶段
| 阶段 | 用途 |
|---|---|
certificate | 动态证书选择(SNI) |
rewrite | 重写 URI、修改请求属性 |
access | 认证、鉴权、限流、路由选择 |
balancer | 负载均衡算法、健康检查 |
header_filter | 修改响应头 |
body_filter | 修改响应体(流式) |
log | 异步日志、指标上报 |
4. Envoy:C++ 性能怪兽与 WASM 扩展
4.1 架构概述
Envoy 是 Lyft 开源的 C++ L7 代理,设计目标是高性能 + 可观测性 + 可扩展性。它是 Istio、AWS App Mesh、Consul Connect 的数据面核心。
核心概念:
- Listener:监听端口,接收下游连接。
- Filter Chain:对流量进行过滤处理(如 HTTP 连接管理、gRPC-JSON 转码)。
- Cluster:上游服务集群,负责负载均衡和健康检查。
- Route:基于 URL、Header 匹配路由到具体 Cluster。
4.2 静态配置示例
# envoy.yaml — Envoy 静态配置示例
static_resources:
listeners:
- name: listener_http
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
codec_type: AUTO
# 路由配置
route_config:
name: local_route
virtual_hosts:
- name: backend
domains: ["*"]
routes:
# 用户服务路由
- match:
prefix: "/api/v1/users"
route:
cluster: user_service_cluster
timeout: 5s
retry_policy:
retry_on: "5xx,connect-failure"
num_retries: 3
per_try_timeout: 2s
# 订单服务路由
- match:
prefix: "/api/v1/orders"
route:
cluster: order_service_cluster
timeout: 10s
# HTTP 过滤器链
http_filters:
# WASM 过滤器(见下文)
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
name: custom_auth_filter
root_id: custom_auth_root
# 运行时配置(配置源见下)
configuration:
"@type": type.googleapis.com/google.protobuf.StringValue
value: '{"auth_header": "Authorization"}'
vm_config:
vm_id: custom_auth_vm
runtime: envoy.wasm.runtime.v8
code:
remote:
http_uri:
uri: https://config.example.com/filters/auth.wasm
cluster: config_cluster
timeout: 10s
sha256: abc123...
# 限流过滤器(基于本地令牌桶)
- 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: 100
tokens_per_fill: 100
fill_interval: 60s
filter_enabled:
runtime_key: local_rate_limit_enabled
default_value:
numerator: 100
denominator: HUNDRED
filter_enforced:
runtime_key: local_rate_limit_enforced
default_value:
numerator: 100
denominator: HUNDRED
# 终端过滤器:路由器
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
# 上游集群定义
clusters:
- name: user_service_cluster
connect_timeout: 1s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
# 连接池配置(性能调优关键)
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 10000
max_pending_requests: 10000
max_requests: 10000
max_retries: 3000
load_assignment:
cluster_name: user_service_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: user-service
port_value: 8080
# 健康检查
health_checks:
- timeout: 2s
interval: 10s
unhealthy_threshold: 3
healthy_threshold: 2
http_health_check:
path: /health
- name: order_service_cluster
connect_timeout: 1s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
load_assignment:
cluster_name: order_service_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: order-service
port_value: 8080
# 远程配置拉取集群
- name: config_cluster
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: config_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: config.example.com
port_value: 443
4.3 WASM 插件开发
Envoy 支持 WebAssembly(WASM)扩展,允许用 Rust、C++、AssemblyScript 编写过滤器,热更新无需重启进程。
// src/lib.rs — Rust 编写的 Envoy WASM 过滤器(基于 proxy-wasm Rust SDK)
// 功能:检查请求头中的 API Key,无效时返回 401
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
use serde_json::Value;
#[no_mangle]
pub fn _start() {
proxy_wasm::set_log_level(LogLevel::Info);
proxy_wasm::set_http_context(|_context_id, root_context_id| -> Box<dyn HttpContext> {
Box::new(ApiKeyAuthFilter {
root_context_id,
auth_header: "X-API-Key".to_string(),
})
});
}
struct ApiKeyAuthFilter {
root_context_id: u32,
auth_header: String,
}
impl Context for ApiKeyAuthFilter {}
impl HttpContext for ApiKeyAuthFilter {
// 请求头到达时触发
fn on_http_request_headers(&mut self, _num_headers: usize, _end_of_stream: bool) -> Action {
// 读取配置(从 Envoy 配置传入)
if let Some(config_bytes) = self.get_plugin_configuration() {
if let Ok(config_str) = std::str::from_utf8(&config_bytes) {
if let Ok(config_json) = serde_json::from_str::<Value>(config_str) {
if let Some(header) = config_json.get("auth_header").and_then(|v| v.as_str()) {
self.auth_header = header.to_string();
}
}
}
}
// 获取请求头中的 API Key
let api_key = self.get_http_request_header(&self.auth_header);
match api_key {
Some(key) if !key.is_empty() && validate_key(&key) => {
// 验证通过,放行请求
Action::Continue
}
_ => {
// 验证失败,返回 401 Unauthorized
self.send_http_response(
401,
vec![("WWW-Authenticate", "Bearer")],
Some(b"Unauthorized: invalid or missing API key"),
);
Action::Pause
}
}
}
}
// 模拟 API Key 验证(生产环境应从 Vault 或 Redis 获取)
fn validate_key(key: &str) -> bool {
const VALID_KEYS: &[&str] = &["prod-key-2026-alpha", "prod-key-2026-beta"];
VALID_KEYS.contains(&key)
}
4.4 xDS 动态配置
Envoy 的强大之处在于支持 xDS(Discovery Service)协议动态获取配置:
- LDS:Listener Discovery Service
- RDS:Route Discovery Service
- CDS:Cluster Discovery Service
- EDS:Endpoint Discovery Service
- SDS:Secret Discovery Service
Istio 的 istiod 就是 xDS 控制面,Envoy Sidecar 启动后通过 gRPC 流订阅配置变更。
5. Spring Cloud Gateway:Java 生态的贴身后卫
5.1 架构概述
Spring Cloud Gateway(SCG)基于 Spring 5、Project Reactor 和 Netty 构建,采用异步非阻塞架构。它的定位是 Spring Cloud 微服务体系中的网关层,与 Eureka、Consul、Config Server 深度集成。
核心组件:
- Route:由 ID、目标 URI、Predicate(断言)和 Filter(过滤器)组成。
- Predicate:匹配条件(如 Path、Header、Cookie、Method)。
- Filter:对请求或响应进行修改(如添加头、重写路径、限流)。
5.2 Java 配置类示例
// GatewayConfig.java — Spring Cloud Gateway 路由与过滤器配置
package com.example.gateway.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRoutes(RouteLocatorBuilder builder) {
return builder.routes()
// 用户服务路由
.route("user-service", r -> r
.path("/api/v1/users/**", "/api/v1/auth/**")
// 基于权重的灰度发布:90% 流量到 v1,10% 到 v2
.weight("user-service-group", 90)
.filters(f -> f
// 剥离前缀(可选)
.stripPrefix(0)
// 添加自定义请求头,传递追踪信息
.addRequestHeader("X-Gateway-Source", "spring-cloud-gateway")
// 重试策略
.retry(retryConfig -> retryConfig
.setRetries(3)
.setStatuses(INTERNAL_SERVER_ERROR, BAD_GATEWAY, SERVICE_UNAVAILABLE)
)
// 熔断降级
.circuitBreaker(circuitBreakerConfig -> circuitBreakerConfig
.setName("userServiceCircuitBreaker")
.setFallbackUri("forward:/fallback/user")
)
)
.uri("lb://user-service")
)
// 订单服务路由(强制 HTTPS)
.route("order-service", r -> r
.path("/api/v1/orders/**")
.and().method("GET", "POST")
.filters(f -> f
.rewritePath("/api/v1/orders/(?<segment>.*)", "/orders/${segment}")
// 请求限流:基于 Redis 的令牌桶
.requestRateLimiter(rateLimiterConfig -> rateLimiterConfig
.setRateLimiter(redisRateLimiter())
.setKeyResolver(apiKeyResolver())
)
)
.uri("lb://order-service")
)
// WebSocket 路由
.route("notification-ws", r -> r
.path("/ws/notifications")
.uri("lb:ws://notification-service")
)
.build();
}
// Redis 限流器:每秒 100 请求,突发 200
@Bean
public RedisRateLimiter redisRateLimiter() {
// 参数: replenishRate(每秒填充速率),burstCapacity(桶容量),requestedTokens(每次消耗令牌数)
return new RedisRateLimiter(100, 200, 1);
}
// 按 API Key 限流(替代默认的按用户限流)
@Bean
public KeyResolver apiKeyResolver() {
return exchange -> {
// 从请求头提取 API Key 作为限流维度
String apiKey = exchange.getRequest().getHeaders().getFirst("X-API-Key");
if (apiKey == null || apiKey.isEmpty()) {
apiKey = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
}
return reactor.core.publisher.Mono.just(apiKey);
};
}
}
5.3 熔断与降级配置
SCG 通过 Resilience4j 或 Spring Cloud Circuit Breaker 实现熔断。
// FallbackController.java — 熔断降级端点
package com.example.gateway.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/fallback")
public class FallbackController {
@GetMapping("/user")
public Mono<String> userServiceFallback() {
// 用户服务不可用时返回降级数据
return Mono.just("{\"error\": \"user_service_unavailable\", \"message\": \"服务暂时不可用,请稍后重试\"}");
}
@GetMapping("/order")
public Mono<String> orderServiceFallback() {
return Mono.just("{\"error\": \"order_service_unavailable\", \"message\": \"订单服务繁忙\"}");
}
}
5.4 application.yml 极简配置
# application.yml — Spring Cloud Gateway 基础配置
server:
port: 8080
spring:
application:
name: api-gateway
cloud:
gateway:
# 全局默认过滤器
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- AddResponseHeader=X-Response-Gateway, SCG-v3.2
# 全局跨域配置
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://app.example.com"
allowedMethods:
- GET
- POST
- PUT
- DELETE
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
# 与 Eureka 集成(可选)
discovery:
locator:
enabled: true
lower-case-service-id: true
# Redis 限流依赖 Redis 连接
redis:
host: redis.example.com
port: 6379
password: ${REDIS_PASSWORD}
lettuce:
pool:
max-active: 100
max-idle: 50
# 熔断器详细配置(Resilience4j)
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 100
permittedNumberOfCallsInHalfOpenState: 10
slowCallDurationThreshold: 2s
slowCallRateThreshold: 80
failureRateThreshold: 50
waitDurationInOpenState: 30s
automaticTransitionFromOpenToHalfOpenEnabled: true
6. KrakenD:超高速聚合网关
6.1 架构概述
KrakenD 是用 Go 编写的高性能 API Gateway,核心特点是无状态、声明式、超快速。它的设计哲学是:在网关层聚合多个后端响应,将 N 次客户端请求合并为 1 次,从而大幅降低延迟。
关键特性:
- 无状态:配置纯静态,不依赖外部数据库,启动即服务。
- 聚合能力:单个端点并行调用多个后端,合并 JSON 响应。
- 属性裁剪:只返回客户端需要的字段,减小带宽。
- 高性能:基于 Go 的 net/http 和 httprouter,P99 延迟极低。
6.2 krakend.json 完整配置
{
"$schema": "https://www.krakend.io/schema/v3.json",
"version": 3,
"name": "KrakenD API Gateway",
"timeout": "5s",
"cache_ttl": "3600s",
"output_encoding": "json",
"port": 8080,
"endpoints": [
{
"endpoint": "/api/v1/dashboard",
"method": "GET",
"output_encoding": "json",
"concurrent_calls": 3,
"timeout": "3s",
"backend": [
{
"url_pattern": "/users/{user_id}",
"host": ["http://user-service:8080"],
"method": "GET",
"group": "user",
"extra_config": {
"backend/http": {
"return_error_details": "user_backend"
}
},
"deny": ["password", "internal_notes"]
},
{
"url_pattern": "/orders?user_id={user_id}",
"host": ["http://order-service:8080"],
"method": "GET",
"group": "orders",
"extra_config": {
"backend/http": {
"return_error_details": "order_backend"
}
},
"deny": ["payment_token"]
},
{
"url_pattern": "/notifications?user_id={user_id}",
"host": ["http://notification-service:8080"],
"method": "GET",
"group": "notifications"
}
],
"extra_config": {
"proxy": {
"flatmap_filter": [
{
"type": "del",
"args": ["user.password"]
}
]
},
"qos/ratelimit/router": {
"max_rate": 500,
"client_capacity": 100,
"strategy": "ip"
}
}
},
{
"endpoint": "/api/v1/products/{product_id}",
"method": "GET",
"backend": [
{
"url_pattern": "/products/{product_id}",
"host": ["http://product-service:8080"],
"method": "GET"
}
],
"extra_config": {
"qos/ratelimit/router": {
"max_rate": 1000,
"client_capacity": 200
},
"modifier/jmespath": {
"expr": "{id: id, name: name, price: price, category: category.name}"
}
}
}
],
"extra_config": {
"telemetry/logging": {
"level": "INFO",
"prefix": "[KRAKEND]",
"syslog": false,
"stdout": true,
"format": "default"
},
"telemetry/metrics": {
"collection_time": "60s",
"proxy_disabled": false,
"router_disabled": false,
"backend_disabled": false,
"endpoint_disabled": false,
"listen_address": "0.0.0.0:8090"
},
"security/cors": {
"allow_origins": ["https://app.example.com"],
"allow_methods": ["GET", "POST", "PUT", "DELETE"],
"allow_headers": ["Authorization", "Content-Type", "X-Request-ID"],
"expose_headers": ["X-Trace-ID", "X-Request-ID"],
"max_age": "12h",
"allow_credentials": true
},
"security/http": {
"allowed_hosts": ["api.example.com"],
"ssl_proxy_headers": {},
"sts_seconds": 300,
"frame_deny": true,
"content_type_nosniff": true,
"browser_xss_filter": true
},
"plugin/http-server": {
"name": ["custom-auth-plugin"],
"custom-auth-plugin": {
"auth_endpoint": "http://auth-service:8080/validate"
}
}
}
}
6.3 聚合响应效果
当客户端请求 GET /api/v1/dashboard?user_id=42 时,KrakenD 并行请求三个后端,返回合并结果:
{
"user": {
"id": 42,
"name": "张三",
"email": "zhangsan@example.com"
},
"orders": [
{ "id": 1001, "total": 299.0, "status": "shipped" },
{ "id": 1002, "total": 59.9, "status": "pending" }
],
"notifications": [
{ "id": 5001, "message": "订单已发货" }
]
}
这种聚合模式也称为 Backend for Frontend(BFF) 的网关层实现,避免了前端多次请求。
7. 十维对比:选型一张表搞定
| 对比维度 | Kong | Envoy | Spring Cloud Gateway | KrakenD |
|---|---|---|---|---|
| 编程语言 | OpenResty (Lua/C) | C++ | Java (Netty) | Go |
| 架构模式 | Edge / Hybrid | Edge / Sidecar / Mesh | Edge (Spring Cloud) | Edge |
| 配置方式 | Admin API / DB-less YAML | 静态 YAML / xDS 动态 | Java DSL / YAML / 配置中心 | 静态 JSON(无状态) |
| 扩展机制 | Lua 插件 | WASM / C++ 过滤器 / Lua | Java Filter / GlobalFilter | Go 插件 / Lua(企业版) |
| 请求聚合 | 需自定义插件 | 需自定义 WASM / 外部服务 | 自定义 Filter | 原生支持,并行聚合 |
| 限流算法 | 本地计数器 / Redis 集群 | 本地令牌桶 / 全局 gRPC | Redis 令牌桶(内置) | 本地令牌桶 / IP 策略 |
| 服务发现 | DNS / Consul / Eureka / K8s | 原生支持 EDS / Strict DNS | Eureka / Consul / K8s(原生) | DNS / Consul / etcd |
| TLS/mTLS | 动态证书 / ACME | 动态 SDS / 全链路 mTLS | JDK TLS(需配置) | TLS(静态证书) |
| 可观测性 | Prometheus / Datadog / Zipkin | 原生 Prometheus / Statsd / OpenTelemetry | Spring Boot Actuator / Micrometer | Prometheus / OpenTelemetry |
| 吞吐量 | 高 | 极高(C++ 异步) | 中高(受 JVM GC 影响) | 极高(Go 轻量) |
关键选型建议
| 场景 | 推荐方案 |
|---|---|
| 需要丰富插件生态、传统运维团队 | Kong |
| 已用 Istio/Service Mesh、追求极致性能 | Envoy |
| 纯 Java/Spring Cloud 生态、团队熟悉 JVM | Spring Cloud Gateway |
| 高频聚合场景、追求低延迟与简单运维 | KrakenD |
8. 高级模式:聚合、BFF 与熔断
8.1 响应聚合模式
聚合模式减少客户端往返,通常由网关并行调用多个服务并合并结果。以下是在 Envoy 中通过 External Processing(ext_proc) 或自建聚合服务实现的思路。
# 聚合模式:Envoy + 独立的 Aggregation Service
# Envoy 将 /api/v1/dashboard 路由到聚合服务,由聚合服务内部调用下游
static_resources:
listeners:
- name: main_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: main
route_config:
virtual_hosts:
- name: aggregation
domains: ["*"]
routes:
- match: { prefix: "/api/v1/dashboard" }
route:
cluster: aggregation_service
timeout: 5s
- match: { prefix: "/api/v1/" }
# 直接透传其他请求
route:
cluster: catch_all_cluster
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: aggregation_service
connect_timeout: 1s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: aggregation_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: aggregation-service, port_value: 8080 }
8.2 Backend for Frontend(BFF)模式
BFF 为不同客户端(iOS、Android、Web、H5)提供定制化的 API 网关层,各自独立演进。
// bff-mobile/middleware/gateway.js — Node.js BFF 层示例
// BFF 负责调用内部微服务,按移动端需求裁剪和聚合数据
const express = require('express');
const axios = require('axios');
const circuitBreaker = require('opossum');
const router = express.Router();
// 创建带熔断器的 HTTP 客户端
const userServiceRequest = async (userId) => {
const response = await axios.get(`http://user-service:8080/users/${userId}`, {
timeout: 2000,
headers: { 'X-Internal-Source': 'bff-mobile' }
});
return response.data;
};
const breaker = new circuitBreaker(userServiceRequest, {
timeout: 3000, // 请求超时
errorThresholdPercentage: 50, // 错误率阈值
resetTimeout: 30000, // 打开后等待 30s 进入半开状态
volumeThreshold: 10 // 最小请求量
});
// 熔断打开时的降级逻辑
breaker.fallback(() => ({
id: null,
name: '用户服务暂不可用',
avatar: '/static/default-avatar.png',
level: 'normal'
}));
// 聚合端点:移动端首页数据
router.get('/mobile/home', async (req, res) => {
const userId = req.headers['x-user-id'];
try {
// 并行调用多个服务(聚合模式)
const [userProfile, promotions, unreadCount] = await Promise.all([
breaker.fire(userId),
axios.get('http://promo-service:8080/active', { timeout: 1000 }).catch(() => ({ data: [] })),
axios.get(`http://notification-service:8080/unread/${userId}`, { timeout: 1000 }).catch(() => ({ data: 0 }))
]);
// 按移动端需求裁剪字段(BFF 核心职责)
res.json({
user: {
name: userProfile.name,
avatar: userProfile.avatar,
level: userProfile.membership_level
},
banners: promotions.data.slice(0, 3), // 只取前 3 个横幅
unread: unreadCount.data
});
} catch (error) {
res.status(502).json({ error: 'home_data_unavailable', detail: error.message });
}
});
module.exports = router;
8.3 熔断器模式(Circuit Breaker)
熔断器防止故障级联,有三种状态:Closed(正常)、Open(熔断)、Half-Open(探测)。
// Resilience4jCircuitBreakerConfig.java — 多服务熔断配置
package com.example.gateway.resilience;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
@Configuration
public class Resilience4jCircuitBreakerConfig {
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
// 用户服务:低延迟、高敏感
CircuitBreakerConfig userConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.slowCallRateThreshold(80)
.slowCallDurationThreshold(Duration.ofMillis(500))
.permittedNumberOfCallsInHalfOpenState(10)
.slidingWindowSize(100)
.waitDurationInOpenState(Duration.ofSeconds(15))
.recordExceptions(java.io.IOException.class, java.util.concurrent.TimeoutException.class)
.build();
// 订单服务:允许较高延迟,容忍度更高
CircuitBreakerConfig orderConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(60)
.slowCallRateThreshold(90)
.slowCallDurationThreshold(Duration.ofSeconds(2))
.permittedNumberOfCallsInHalfOpenState(5)
.slidingWindowSize(50)
.waitDurationInOpenState(Duration.ofSeconds(30))
.build();
return CircuitBreakerRegistry.ofDefaults()
.circuitBreaker("userServiceCircuitBreaker", userConfig)
.circuitBreaker("orderServiceCircuitBreaker", orderConfig);
}
}
9. 安全加固:OAuth2、API Key 与 WAF
9.1 OAuth2 / OIDC 集成(Kong 示例)
# 在 kong.yml 中配置 OAuth2 / OIDC 插件
plugins:
- name: openid-connect
service: user-service
config:
# 身份提供商(IdP)发现端点
issuer: https://auth.example.com/realms/production
client_id:
- gateway-client
client_secret:
- ${OIDC_CLIENT_SECRET}
# 令牌验证方式:introspection(自省)或 jwk(本地公钥)
auth_methods:
- bearer
bearer_token_param_type:
- header
# 令牌自省端点(推荐生产使用,支持撤销检查)
introspection_endpoint: https://auth.example.com/realms/production/protocol/openid-connect/token/introspect
introspection_client_id: introspection-client
introspection_client_secret: ${INTROSPECTION_SECRET}
# 缓存自省结果,减少 IdP 压力
introspection_cache_ttl: 300
# 权限提取
scopes_required:
- read:users
- write:users
scopes_claim:
- scope
- scopes
# 用户信息转发给上游
upstream_headers_claims:
- sub
- preferred_username
- email
upstream_headers_names:
- X-User-ID
- X-Username
- X-User-Email
redirect_uri:
- https://api.example.com/callback
9.2 API Key 管理(Envoy WASM + 外部验证)
前文已展示 WASM 校验 API Key 的 Rust 代码。生产环境建议搭配 API Key 管理后台,支持按应用、环境、有效期维度管理密钥,并在网关层通过高速缓存(如 Redis)减少外部验证延迟。
# Envoy 搭配外部授权服务(ExtAuthz)进行 API Key 校验
http_filters:
- name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: ext_authz_cluster
timeout: 0.5s
include_peer_certificate: false
transport_api_version: V3
# 校验通过后,将外部服务返回的头信息传递给上游
metadata_context_namespaces:
- envoy.filters.http.ext_authz
9.3 Web Application Firewall(WAF)
WAF 在网关层拦截 SQL 注入、XSS、恶意爬虫等攻击。
# ModSecurity WAF 集成(常见搭配 Nginx / OpenResty)
# 在 Kong/nginx.conf 中加载 ModSecurity
server {
listen 443 ssl;
server_name api.example.com;
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
# 启用 OWASP Core Rule Set(CRS)
modsecurity_rules '
SecRuleEngine On
SecRequestBodyAccess On
SecResponseBodyAccess On
SecResponseBodyLimit 524288
# 自定义规则:拦截特定 User-Agent
SecRule REQUEST_HEADERS:User-Agent "@contains BadBot" \
"id:1000,phase:1,deny,status:403,msg:\'Blocked BadBot\'"
';
location / {
proxy_pass http://upstream_backend;
}
}
10. 性能调优实战
10.1 连接池调优
连接复用是网关性能的核心。每次新建 TCP 连接的三次握手和 TLS 握手会显著增加延迟。
# Envoy 连接池与 HTTP2 调优
clusters:
- name: high_perf_upstream
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
# HTTP/2 上游支持(启用多路复用)
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
upstream_protocol_options:
explicit_http_config:
http2_protocol_options: {}
# HTTP 连接池配置
common_http_protocol_options:
idle_timeout: 3600s
upstream_connection_options:
tcp_keepalive:
keepalive_probes: 3
keepalive_time: 300
keepalive_interval: 75
# 负载均衡健康检查
health_checks:
- timeout: 1s
interval: 5s
healthy_threshold: 1
unhealthy_threshold: 3
http_health_check:
path: /health
expected_statuses:
start: 200
end: 200
10.2 响应缓存
# Kong 响应缓存插件配置
plugins:
- name: proxy-cache
config:
response_code:
- 200
- 301
- 404
request_method:
- GET
- HEAD
content_type:
- text/plain
- application/json
cache_ttl: 300
strategy: memory
# 按 Host + URI 生成缓存键
cache_key_use_host: true
cache_key_use_uri: true
# 需要绕过的头
vary_headers:
- Accept-Language
10.3 压缩
# Envoy Gzip 压缩过滤器
http_filters:
- name: envoy.filters.http.compressor
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.compressor.v3.Compressor
response_direction_config:
common_config:
min_content_length: 100
content_type:
- text/plain
- text/html
- application/json
- application/javascript
compressor_library:
name: text_optimized
typed_config:
"@type": type.googleapis.com/envoy.extensions.compression.gzip.compressor.v3.Gzip
memory_level: 5
compression_level: BEST_SPEED
compression_strategy: DEFAULT_STRATEGY
window_bits: 12
11. Kubernetes 生产部署:Ingress + Helm
11.1 Kong Ingress Controller(Helm)
# 添加 Kong Helm 仓库
helm repo add kong https://charts.konghq.com
helm repo update
# 生产级安装:PostgreSQL + Ingress Controller + 监控
helm install kong kong/kong \
--namespace gateway \
--create-namespace \
--set ingressController.enabled=true \
--set ingressController.installCRDs=true \
--set postgresql.enabled=true \
--set postgresql.auth.username=kong \
--set postgresql.auth.password="$(openssl rand -base64 16)" \
--set proxy.type=LoadBalancer \
--set proxy.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-type"="nlb" \
--set proxy.annotations."service\.beta\.kubernetes\.io/aws-load-balancer-cross-zone-load-balancing-enabled"="true" \
--set resources.requests.cpu=1000m \
--set resources.requests.memory=2Gi \
--set resources.limits.cpu=4000m \
--set resources.limits.memory=4Gi \
--set autoscaling.enabled=true \
--set autoscaling.minReplicas=3 \
--set autoscaling.maxReplicas=20 \
--set autoscaling.targetCPUUtilizationPercentage=70 \
--set podDisruptionBudget.enabled=true \
--set podDisruptionBudget.minAvailable=2 \
--set metrics.enabled=true \
--set metrics.serviceMonitor.enabled=true
# 部署后创建 Ingress 规则
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-ingress
namespace: default
annotations:
konghq.com/strip-path: "false"
konghq.com/plugins: rate-limit-100, jwt-auth
spec:
ingressClassName: kong
rules:
- host: api.example.com
http:
paths:
- path: /api/v1/users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 8080
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 8080
11.2 Istio Gateway + 自动注入
# Istio 生产安装(精简版)
istioctl install --set profile=default \
--set meshConfig.accessLogFile=/dev/stdout \
--set meshConfig.enableAutoMtls=true \
--set values.global.proxy.resources.requests.cpu=100m \
--set values.global.proxy.resources.requests.memory=128Mi \
--set values.global.proxy.resources.limits.cpu=2000m \
--set values.global.proxy.resources.limits.memory=1Gi
# 为命名空间启用自动 Sidecar 注入
kubectl label namespace default istio-injection=enabled --overwrite
# 生产级 Istio Gateway + VirtualService(灰度发布)
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: production-gateway
namespace: istio-system
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: api-tls-cert
hosts:
- api.example.com
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: user-service-canary
namespace: default
spec:
hosts:
- api.example.com
gateways:
- istio-system/production-gateway
http:
- match:
- headers:
x-canary:
exact: "true"
route:
- destination:
host: user-service
subset: v2
weight: 100
- route:
- destination:
host: user-service
subset: v1
weight: 95
- destination:
host: user-service
subset: v2
weight: 5
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: user-service-versions
namespace: default
spec:
host: user-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1000
http:
http1MaxPendingRequests: 500
http2MaxRequests: 1000
loadBalancer:
simple: LEAST_CONN
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
12. FAQ
Q1:API Gateway 与反向代理(Nginx)的核心区别是什么?
Nginx 作为反向代理主要负责四层/七层转发、负载均衡和静态资源服务。API Gateway 在此基础上增加了业务语义——认证鉴权、协议转换、请求/响应转换、限流熔断、灰度发布、日志追踪等。简言之,Nginx 是基础设施,API Gateway 是应用层组件。
Q2:服务 already 使用了 Sidecar(Envoy),还需要单独的 Edge Gateway 吗?
建议保留。Sidecar 主要处理东西向流量(服务间通信),Edge Gateway 处理南北向流量(外部客户端)。Istio Gateway 本身就是一种 Edge Gateway,它将 Envoy 部署在网格边缘,统一收口外部流量并接入 mTLS。如果没有 Service Mesh,独立的 Kong / KrakenD 作为 Edge Gateway 仍是最佳实践。
Q3:Kong 的 DB-less 模式和高可用模式(Hybrid)如何选择?
- DB-less 模式:配置通过
kong.yml声明式管理,适合容器化、GitOps、配置变更不频繁的场景。Kong 节点完全无状态,重启即恢复。 - Hybrid 模式:CP 使用 PostgreSQL 存储,DP 通过 gRPC 从 CP 同步配置。适合大规模集群(100+ 节点)、需要 Admin API 动态下发配置、多集群联邦治理的场景。
Q4:Spring Cloud Gateway 的性能瓶颈通常在哪里?如何解决?
主要瓶颈有三:
- JVM GC:长耗时 GC 导致请求暂停。建议使用 G1 / ZGC,并合理设置堆内存。
- 阻塞式 Filter:自定义 Filter 中使用了阻塞 I/O(如 JDBC、同步 HTTP)。应全部替换为 Reactive 流(WebClient / R2DBC)。
- 限流 Redis RTT:每次请求都去 Redis 取令牌。可通过本地缓存 + 异步批量同步策略优化,或改用本地限流(牺牲全局一致性)。
Q5:KrakenD 的并发调用如果某个后端失败,如何处理?
KrakenD 默认采用 “尽力聚合” 策略。单个后端失败时,其他后端的结果仍然返回,失败的后端字段包含错误信息(需开启 return_error_details)。如果业务要求全部成功才返回,可以通过 Sequential Proxy 插件实现串行调用,或者在外部聚合服务中自行实现事务补偿逻辑。
13. 总结与选型建议
API Gateway 是微服务架构的咽喉要道,选型需综合考虑团队技术栈、性能需求、运维能力和生态兼容性。
- Kong 凭借 Lua 插件生态和成熟的社区支持,是大多数传统企业的稳妥选择。DB-less 模式让它在云原生时代依然游刃有余。
- Envoy 凭借 C++ 原生性能、WASM 扩展能力和 xDS 动态配置,是 Service Mesh 时代的事实标准。若已采用 Istio,Envoy 是无需额外选型的默认答案。
- Spring Cloud Gateway 与 Java 生态无缝衔接,适合已深度使用 Spring Boot / Spring Cloud 的团队。其异步非阻塞架构在 JVM 生态中表现优异,但需警惕 GC 和阻塞操作的陷阱。
- KrakenD 以无状态、原生聚合和高吞吐著称,是前端聚合(BFF)和高性能边缘网关的利器。配置极简,运维成本极低。
在生产环境中,分层网关策略往往最有效:
- L4 层:云厂商 Load Balancer(如 AWS NLB、阿里云 SLB)负责证书卸载和 DDoS 清洗。
- L7 Edge 层:Kong / KrakenD / Istio Gateway 负责路由、认证、限流、灰度。
- Service Mesh 层:Envoy Sidecar 负责东西向流量治理、熔断、mTLS。
通过分层,每一层各司其责,既避免了单点过载,又保证了架构的可演进性。最终,网关的选型不是技术崇拜,而是对业务场景和团队能力的精准匹配。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。