跳到主要内容
Spring Cloud Gateway 路由、过滤器与限流机制详解 | 极客日志
Java java 算法
Spring Cloud Gateway 路由、过滤器与限流机制详解 Spring Cloud Gateway 基于 WebFlux 响应式模型实现高性能 API 网关。文章解析其核心架构、路由匹配机制、过滤器链执行顺序及自定义开发方法。重点介绍分布式限流(令牌桶算法)与熔断降级策略,并结合电商场景提供完整配置示例、性能优化方案及生产环境故障排查指南。涵盖静态/动态路由、服务发现集成及安全认证过滤器的企业级实践。
赛博行者 发布于 2026/2/4 更新于 2026/6/2 6.9K 浏览API 网关:微服务架构的枢纽
为什么需要 API 网关?
在微服务化项目中,常因缺乏统一 API 网关导致代码重复且难以维护。客户端需要知道每个服务的具体地址,一旦服务地址变更,所有客户端都需要更新。
API 网关的核心价值在于它作为系统的唯一入口,统一处理所有客户端请求,实现了关注点分离。
Spring Cloud Gateway vs 传统方案
与 Nginx、Zuul 等传统方案相比,Spring Cloud Gateway 具有明显优势:
特性 Nginx Zuul 1.x Spring Cloud Gateway 编程模型 同步阻塞 同步阻塞 异步非阻塞 性能 高 低 高 可扩展性 中等 高 高 Spring 生态集成 弱 强 原生支持 配置方式 文件配置 注解/配置 声明式配置
性能测试数据 (每秒请求数,100 并发连接):
Nginx: 12,500 RPS
Zuul 1.x: 3,200 RPS
Spring Cloud Gateway: 11,800 RPS
虽然绝对性能略低于 Nginx,但 Spring Cloud Gateway 提供了更好的编程灵活性和 Spring 生态集成能力。
Spring Cloud Gateway 架构深度解析
核心架构设计
Spring Cloud Gateway 采用分层架构设计,核心组件协同工作:
核心组件说明 :
RoutePredicateHandlerMapping:路由匹配,决定请求应该由哪个路由处理
FilteringWebHandler:执行过滤器链,包括全局过滤器和路由过滤器
NettyRoutingFilter:实际转发请求到后端服务
ServerWebExchange:封装请求和响应上下文的核心对象
响应式编程模型
Spring Cloud Gateway 基于 Project Reactor 实现响应式编程,这是其高性能的关键:
public class GatewayReactiveExample {
public Mono<Void> handleRequest (ServerWebExchange exchange) {
return Mono.fromRunnable(() -> {
log.info( , exchange.getRequest().getPath());
})
.subscribeOn(Schedulers.boundedElastic())
.then(chain.filter(exchange))
.doOnSuccess(v -> log.info( ))
.doOnError(e -> log.error( , e));
}
Flux<DataBuffer> {
exchange.getRequest().getBody()
.map(dataBuffer -> {
processDataBuffer(dataBuffer);
})
.take( )
.timeout(Duration.ofSeconds( ));
}
}
"处理请求:{}"
"请求处理成功"
"请求处理失败"
public
handleStreamingRequest
(ServerWebExchange exchange)
return
return
1000
30
路由机制:流量指挥的艺术
静态路由配置 spring:
cloud:
gateway:
routes:
- id: user_service_route
uri: http://localhost:8081
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- AddRequestHeader=X-Gateway-Request, true
- id: order_service_route
uri: http://localhost:8082
predicates:
- Path=/api/orders/**
- Method=GET,POST
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"
id:路由唯一标识,便于管理和监控
uri:目标服务地址,支持 lb:// 服务发现集成
predicates:路由匹配条件,支持路径、方法、Header 等
filters:请求处理过滤器链
动态路由实现 生产环境中,动态路由是必备能力。推荐基于数据库的动态路由方案:
@Entity
@Table(name = "gateway_routes")
public class GatewayRouteEntity {
@Id
private String id;
private String uri;
@Column(columnDefinition = "TEXT")
private String predicates;
@Column(columnDefinition = "TEXT")
private String filters;
private Integer routeOrder;
private Boolean enabled;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
@Component
public class DatabaseRouteDefinitionRepository implements RouteDefinitionRepository {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private GatewayRouteService routeService;
@Override
public Flux<RouteDefinition> getRouteDefinitions () {
return Flux.fromIterable(routeService.findAllEnabledRoutes())
.map(this ::convertToRouteDefinition);
}
@EventListener
public void handleRouteAdd (RouteAddEvent event) {
RouteDefinition routeDefinition = event.getRouteDefinition();
routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
applicationContext.publishEvent(new RefreshRoutesEvent (this ));
}
@EventListener
public void handleRouteDelete (RouteDeleteEvent event) {
routeDefinitionWriter.delete(Mono.just(event.getRouteId())).subscribe();
applicationContext.publishEvent(new RefreshRoutesEvent (this ));
}
}
服务发现集成 Spring Cloud Gateway 与 Nacos、Eureka 等服务发现组件无缝集成:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
routes:
- id: user_service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- RewritePath=/api/users/(?<segment>.*), /${segment}
- id: order_service
uri: lb://order-service
predicates:
- Path=/api/orders/**
- Header=X-Requested-With, XMLHttpRequest
这种配置下,网关会自动从注册中心获取服务实例列表,并实现负载均衡。
过滤器链:请求处理的灵魂
过滤器类型与执行顺序 Spring Cloud Gateway 的过滤器分为两大类,执行顺序由 Ordered 接口控制:
@Component
public class AuthFilter implements GlobalFilter , Ordered {
@Override
public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization" );
if (!validateToken(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder () {
return -100 ;
}
}
@Component
public class LoggingFilter implements GlobalFilter , Ordered {
@Override
public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).doOnSuccessOrError((v, e) -> {
long duration = System.currentTimeMillis() - startTime;
log.info("请求路径:{}, 耗时:{}ms, 状态:{}" , exchange.getRequest().getPath(), duration, exchange.getResponse().getStatusCode());
});
}
@Override
public int getOrder () {
return 0 ;
}
}
常用内置过滤器详解 Spring Cloud Gateway 提供了丰富的内置过滤器:
spring:
cloud:
gateway:
routes:
- id: enhanced_route
uri: lb://backend-service
predicates:
- Path=/api/**
filters:
- RewritePath=/api/(?<segment>.*), /${segment}
- AddRequestHeader=X-Request-Gateway, true
- RemoveRequestHeader=Secret-Header
- SetRequestHeader=X-User-ID, 12345
- AddResponseHeader=X-Response-Gateway, processed
- SetResponseHeader=X-Cache-Hit, false
- name: Retry
args:
retries: 3
methods: GET,POST
statuses: BAD_GATEWAY,SERVICE_UNAVAILABLE
backoff:
firstBackoff: 10ms
maxBackoff: 100ms
factor: 2
basedOnPreviousValue: false
- name: CircuitBreaker
args:
name: backendServiceBreaker
fallbackUri: forward:/fallback/serviceUnavailable
自定义过滤器开发 实际项目中,经常需要开发自定义过滤器满足特定业务需求:
@Component
public class RateLimitByUserGatewayFilterFactory extends AbstractGatewayFilterFactory <RateLimitByUserGatewayFilterFactory.Config> {
@Autowired
private RedisTemplate<String, Integer> redisTemplate;
public RateLimitByUserGatewayFilterFactory () {
super (Config.class);
}
@Override
public GatewayFilter apply (Config config) {
return (exchange, chain) -> {
String userId = getUserId(exchange);
String key = "rate_limit:" + config.getType() + ":" + userId;
Long current = redisTemplate.opsForValue().increment(key, 1 );
if (current == 1 ) {
redisTemplate.expire(key, config.getWindowSeconds(), TimeUnit.SECONDS);
}
if (current > config.getMaxRequests()) {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUISITIONS);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
};
}
public static class Config {
private String type;
private int maxRequests;
private int windowSeconds;
}
}
@Bean
public RouteLocator customRouteLocator (RouteLocatorBuilder builder) {
return builder.routes()
.route("user_limited_route" , r -> r.path("/api/users/**" )
.filters(f -> f.filter(new RateLimitByUserGatewayFilterFactory ()
.apply(new Config ("user_api" , 100 , 60 ))))
.uri("lb://user-service" ))
.build();
}
限流熔断:系统稳定的守护神
分布式限流实现 在高并发场景下,分布式限流是保护后端服务的关键技术:
spring:
cloud:
gateway:
routes:
- id: limited_route
uri: lb://backend-service
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
redis-rate-limiter.requestedTokens: 1
key-resolver: "#{@apiKeyResolver}"
@Configuration
public class RateLimitConfig {
@Bean
public KeyResolver userKeyResolver () {
return exchange -> {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-ID" );
if (StringUtils.isEmpty(userId)) {
String token = extractToken(exchange);
userId = jwtHelper.getUserIdFromToken(token);
}
return Mono.just(StringUtils.isEmpty(userId) ? "anonymous" : userId);
};
}
@Bean
public KeyResolver ipKeyResolver () {
return exchange -> {
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
return Mono.just(ip);
};
}
@Bean
public KeyResolver apiKeyResolver () {
return exchange -> {
String path = exchange.getRequest().getPath().value();
String method = exchange.getRequest().getMethodValue();
return Mono.just(method + ":" + path);
};
}
}
令牌桶算法深度解析 Spring Cloud Gateway 基于令牌桶算法实现限流,其核心原理如下:
public class TokenBucketRateLimiter {
private final int capacity;
private final double refillRate;
private double tokens;
private long lastRefillTimestamp;
public synchronized boolean tryAcquire (int tokensRequested) {
refillTokens();
if (tokens >= tokensRequested) {
tokens -= tokensRequested;
return true ;
}
return false ;
}
private void refillTokens () {
long now = System.currentTimeMillis();
if (now > lastRefillTimestamp) {
double secondsSinceLastRefill = (now - lastRefillTimestamp) / 1000.0 ;
double tokensToAdd = secondsSinceLastRefill * refillRate;
tokens = Math.min(capacity, tokens + tokensToAdd);
lastRefillTimestamp = now;
}
}
}
public class RedisRateLimiterScript {
private static final String LUA_SCRIPT = "local tokens_key = KEYS[1]\n" +
"local timestamp_key = KEYS[2]\n" +
"local rate = tonumber(ARGV[1])\n" +
"local capacity = tonumber(ARGV[2])\n" +
"local now = tonumber(ARGV[3])\n" +
"local requested = tonumber(ARGV[4])\n" +
"local fill_time = capacity / rate\n" +
"local ttl = math.floor(fill_time * 2)\n" +
"local last_tokens = tonumber(redis.call('get', tokens_key) or capacity)\n" +
"local last_refreshed = tonumber(redis.call('get', timestamp_key) or 0)\n" +
"local delta = math.max(0, now - last_refreshed)\n" +
"local filled_tokens = math.min(capacity, last_tokens + (delta * rate))\n" +
"local allowed = filled_tokens >= requested\n" +
"local new_tokens = filled_tokens\n" +
"local allowed_num = 0\n" +
"if allowed then\n" +
" new_tokens = filled_tokens - requested\n" +
" allowed_num = 1\n" +
"end\n" +
"redis.call('setex', tokens_key, ttl, new_tokens)\n" +
"redis.call('setex', timestamp_key, ttl, now)\n" +
"return { allowed_num, new_tokens }" ;
}
熔断降级策略 @Configuration
public class CircuitBreakerConfig {
@Bean
public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultConfig () {
return factory -> {
factory.configureDefault(id -> new CircuitBreakerConfig .Builder()
.slidingWindowType(SlidingWindowType.TIME_BASED)
.slidingWindowSize(100 )
.minimumNumberOfCalls(10 )
.failureRateThreshold(50 )
.waitDurationInOpenState(Duration.ofSeconds(60 ))
.permittedNumberOfCallsInHalfOpenState(10 )
.recordExceptions(IOException.class, TimeoutException.class)
.build());
};
}
}
@Bean
public RouteLocator circuitBreakerRoute (RouteLocatorBuilder builder) {
return builder.routes()
.route("circuit_breaker_route" , r -> r.path("/api/unstable/**" )
.filters(f -> f.circuitBreaker(config -> config
.setName("backendBreaker" )
.setFallbackUri("forward:/fallback/unavailable" )))
.uri("lb://unstable-service" ))
.build();
}
@RestController
public class FallbackController {
@GetMapping("/fallback/unavailable")
public Mono<ResponseEntity<Map<String, Object>>> serviceUnavailable () {
return Mono.just(ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.body(Map.of(
"code" , 503 ,
"message" , "服务暂时不可用,请稍后重试" ,
"timestamp" , System.currentTimeMillis()
)));
}
}
企业级实战案例:电商系统网关设计
电商网关架构设计
完整配置示例 spring:
cloud:
gateway:
httpclient:
connect-timeout: 5000
response-timeout: 30s
pool:
max-connections: 1000
acquire-timeout: 5000
routes:
- id: user_service_v1
uri: lb://user-service
predicates:
- Path=/api/v1/users/**
- Header=X-API-Version, v1
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 50
redis-rate-limiter.burstCapacity: 100
key-resolver: "#{@userKeyResolver}"
- CacheRequestBody
- name: CircuitBreaker
args:
name: userServiceBreaker
fallbackUri: forward:/fallback/userUnavailable
- id: product_service_v2
uri: lb://product-service
predicates:
- Path=/api/v2/products/**
- Header=X-API-Version, v2
filters:
- StripPrefix=1
- RewritePath=/api/v2/products/(?<segment>.*), /${segment}
- AddResponseHeader=X-API-Version, v2
- id: order_service_canary
uri: lb://order-service-v2
predicates:
- Path=/api/orders/**
- Header=X-User-Type, premium
filters:
- StripPrefix=1
- AddRequestHeader=X-Canary, true
- id: order_service_default
uri: lb://order-service-v1
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
management:
endpoints:
web:
exposure:
include: health,info,metrics,gateway
endpoint:
gateway:
enabled: true
redis:
host: ${REDIS_HOST:localhost}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:}
database: 0
timeout: 2000
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
安全认证过滤器 @Component
public class SecurityFilter implements GlobalFilter , Ordered {
@Autowired
private JwtHelper jwtHelper;
@Autowired
private BlacklistService blacklistService;
@Override
public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) {
String clientIp = getClientIp(exchange);
if (blacklistService.isIpBlocked(clientIp)) {
return unauthorizedResponse(exchange, "IP 地址被限制访问" );
}
if (isExcludedPath(exchange.getRequest().getPath().value())) {
return chain.filter(exchange);
}
String token = extractToken(exchange);
if (!jwtHelper.validateToken(token)) {
return unauthorizedResponse(exchange, "令牌无效或已过期" );
}
String path = exchange.getRequest().getPath().value();
String method = exchange.getRequest().getMethodValue();
if (!hasPermission(token, path, method)) {
return forbiddenResponse(exchange, "权限不足" );
}
String userId = jwtHelper.getUserIdFromToken(token);
exchange = exchange.mutate()
.request(builder -> builder.header("X-User-ID" , userId))
.build();
return chain.filter(exchange);
}
@Override
public int getOrder () {
return HIGHEST_PRECEDENCE;
}
private boolean isExcludedPath (String path) {
return path.startsWith("/public/" ) || path.equals("/health" ) || path.startsWith("/actuator/" );
}
}
性能优化与监控
网关性能优化策略
server:
netty:
connection-timeout: 5000
idle-timeout: 60s
reactor:
netty:
io-worker-count: 16
allocator:
max-order: 3
chunk-size: 16MB
spring:
cloud:
gateway:
httpclient:
pool:
type: elastic
max-connections: 1000
acquire-timeout: 5000
max-idle-time: 60s
-Xms2g -Xmx2g
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:G1ReservePercent=25
-XX:InitiatingHeapOccupancyPercent=30
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/logs/gateway/heapdump.hprof
监控与告警
management:
metrics:
export:
prometheus:
enabled: true
datadog:
enabled: false
web:
server:
request:
autotime:
enabled: true
distribution:
percentiles-histogram:
http.server.requests: true
endpoint:
metrics:
enabled: true
prometheus:
enabled: true
tracing:
sampling:
probability: 0.1
网关吞吐量 :gateway.requests.total
请求延迟 :gateway.requests.duration
限流情况 :gateway.requests.limited
错误率 :gateway.errors.total
JVM 指标 :内存使用、GC 情况
生产环境故障排查指南
常见问题及解决方案
@RestController
@RequestMapping("/gateway/debug")
public class GatewayDebugController {
@Autowired
private RouteLocator routeLocator;
@GetMapping("/routes")
public Flux<Route> listRoutes () {
return routeLocator.getRoutes()
.doOnNext(route -> {
log.info("路由 ID: {}, URI: {}, 顺序:{}" , route.getId(), route.getUri(), route.getOrder());
});
}
@GetMapping("/match")
public Mono<Route> matchRoute (@RequestParam String path) {
return routeLocator.getRoutes()
.filter(route -> {
ServerWebExchange exchange = createMockExchange(path);
return route.getPredicate().test(exchange);
})
.next();
}
}
@Component
public class MemoryMonitor {
@Scheduled(fixedRate = 60000)
public void monitorMemory () {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
double heapUsedPercent = (double ) heapUsage.getUsed() / heapUsage.getMax() * 100 ;
double nonHeapUsedPercent = (double ) nonHeapUsage.getUsed() / nonHeapUsage.getMax() * 100 ;
if (heapUsedPercent > 80 ) {
log.warn("堆内存使用率过高:{}%" , String.format("%.2f" , heapUsedPercent));
System.gc();
}
if (nonHeapUsedPercent > 90 ) {
log.error("非堆内存使用率过高:{}%" , String.format("%.2f" , nonHeapUsedPercent));
dumpThreadStacks();
}
}
}
技术选型与未来展望
网关技术选型建议 场景 推荐方案 理由 Spring Cloud 技术栈 Spring Cloud Gateway 生态集成度高,编程模型一致 高性能要求 Nginx + OpenResty 纯 C 开发,性能极致 多语言技术栈 Kong/APISIX Lua 插件生态丰富 Service Mesh 集成 Istio Gateway 与服务网格深度集成
未来发展趋势
云原生网关 :与 Kubernetes、Service Mesh 深度集成
AI 智能路由 :基于机器学习的智能流量调度
API 治理平台 :统一的 API 生命周期管理
边缘计算网关 :适应物联网和边缘计算场景
参考资源
官方文档
性能基准
最佳实践 相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online