引言
API网关是微服务架构中的流量入口,承担着路由转发、协议转换、统一鉴权、流量控制等核心职责。一个优秀的网关设计能够显著降低服务复杂度,提升系统可观测性。
本文将从架构设计角度出发,深入分析API网关的核心模式,并提供多种技术栈的实战配置。
API网关的核心职责
统一入口与路由
API网关作为系统的单一入口,对外暴露统一的服务地址,内部通过路由规则将请求分发到不同的后端服务。
# Kong 路由配置示例
services:
- name: user-service
url: http://user-service:8080
routes:
- name: user-routes
paths:
- /api/v1/users
methods:
- GET
- POST
- PUT
- DELETE
strip_path: false
preserve_host: true
协议转换
网关可以将外部HTTP/REST请求转换为内部gRPC调用,实现协议解耦。
# Envoy HTTP to gRPC 转换配置
routes:
- match:
prefix: "/api/v1/orders"
route:
cluster: order-service-grpc
grpc: {}
统一鉴权
在网关层实现JWT验证、OAuth2.0认证,避免每个服务重复实现。
-- Kong JWT 插件配置
local jwt = require "resty.jwt"
local function validate_token()
local token = ngx.req.get_headers()["Authorization"]
if not token then
return ngx.exit(401)
end
local jwt_obj = jwt:verify(SECRET_KEY, token:sub(8))
if not jwt_obj.verified then
return ngx.exit(401)
end
ngx.ctx.user_id = jwt_obj.payload.sub
end
动态路由策略
基于权重的灰度发布
通过配置流量权重,实现蓝绿部署或金丝雀发布。
# Kong 蓝绿部署配置
upstreams:
- name: order-service
targets:
- target: order-service-blue:8080
weight: 90
- target: order-service-green:8080
weight: 10
基于Header的流量路由
根据请求头中的特定字段(如租户ID、用户等级)路由到不同版本的服务。
// 自研网关路由决策示例
func (r *Router) Route(req *http.Request) string {
tenantID := req.Header.Get("X-Tenant-ID")
userTier := req.Header.Get("X-User-Tier")
// VIP用户路由到高性能集群
if userTier == "premium" {
return "http://premium-service:8080"
}
// 特定租户路由到独立集群
if tenant, ok := r.tenantRoutes[tenantID]; ok {
return tenant.Endpoint
}
return "http://default-service:8080"
}
流量控制与限流
多维度限流策略
支持基于IP、用户ID、API Key等多个维度的限流。
# Kong Rate Limiting 插件配置
plugins:
- name: rate-limiting
config:
minute: 100
hour: 1000
limit_by: consumer
policy: redis
redis_host: redis-cluster
fault_tolerant: true
自适应限流
根据系统负载动态调整限流阈值,避免雪崩效应。
// 自适应限流实现
type AdaptiveLimiter struct {
baseLimit int
currentLimit int
cpuThreshold float64
memThreshold float64
}
func (a *AdaptiveLimiter) AdjustLimit() {
cpuUsage := metrics.GetCPUUsage()
memUsage := metrics.GetMemoryUsage()
if cpuUsage > a.cpuThreshold || memUsage > a.memThreshold {
// 系统负载高,降低限流阈值
a.currentLimit = int(float64(a.baseLimit) * 0.7)
} else if cpuUsage < a.cpuThreshold*0.5 {
// 系统负载低,恢复限流阈值
a.currentLimit = a.baseLimit
}
}
熔断与降级
服务熔断配置
当后端服务失败率达到阈值时,自动触发熔断,快速失败避免级联故障。
# Envoy 熔断器配置
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 1024
max_pending_requests: 1024
max_requests: 1024
max_retries: 3
track_remaining: true
降级策略
当服务不可用时,返回缓存数据或默认响应。
// 网关层降级处理
func (g *Gateway) handleWithFallback(ctx context.Context, req *http.Request) (*http.Response, error) {
resp, err := g.forward(ctx, req)
if err != nil || resp.StatusCode >= 500 {
// 尝试从缓存获取降级响应
cachedResp, cacheErr := g.cache.Get(g.buildCacheKey(req))
if cacheErr == nil {
return cachedResp, nil
}
// 返回默认响应
return g.buildDefaultResponse(req), nil
}
return resp, nil
}
可观测性增强
分布式追踪集成
在网关层注入Trace ID,串联整个调用链路。
// OpenTelemetry 追踪注入
func (g *Gateway) InjectTrace(ctx context.Context, req *http.Request) context.Context {
tracer := otel.Tracer("api-gateway")
ctx, span := tracer.Start(ctx, fmt.Sprintf("%s %s", req.Method, req.URL.Path))
defer span.End()
// 将Trace ID注入请求头
traceID := span.SpanContext().TraceID().String()
req.Header.Set("X-Trace-ID", traceID)
return ctx
}
指标采集
采集网关层的关键指标:QPS、延迟、错误率、流量分布。
# Prometheus 指标配置
metrics:
- name: gateway_requests_total
type: counter
labels:
- method
- path
- status_code
- upstream_service
- name: gateway_request_duration_seconds
type: histogram
labels:
- method
- path
- upstream_service
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10]
主流网关技术选型对比
| 特性 | Kong | Envoy | Nginx | 自研网关 |
|---|---|---|---|---|
| 性能 | 高 | 极高 | 极高 | 取决于实现 |
| 动态配置 | 支持 | 支持(xDS) | 需reload | 完全可控 |
| 插件生态 | 丰富 | 较少 | 中等 | 需自研 |
| 学习曲线 | 中等 | 陡峭 | 平缓 | 陡峭 |
| 适用场景 | 通用网关 | Service Mesh | 简单代理 | 定制化需求 |
总结
API网关是微服务架构的关键组件,设计时需要综合考虑:
- 路由灵活性:支持多维度路由策略,满足灰度发布、A/B测试等需求
- 统一治理:在网关层实现鉴权、限流、熔断等横切关注点
- 性能与稳定性:选择高性能技术栈,配合熔断降级保障可用性
- 可观测性:集成追踪、指标、日志,提供全链路可视化
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。