Spring Cloud Gateway 2026.x 自定义过滤器链与限流熔断实战
·
前言
在微服务架构中,API网关作为系统的唯一入口,承担着路由转发、负载均衡、安全认证、限流熔断等核心职责。Spring Cloud Gateway 作为 Spring 生态中的第二代网关,基于 Spring 5、Spring Boot 2 和 Project Reactor 构建,具备非阻塞、高性能的特性。
随着 Spring Cloud 2026.x 版本的发布,Gateway 模块迎来了多项重要更新:
- 支持基于 Virtual Threads 的请求处理优化
- 全新的限流熔断集成方案
- 增强的过滤器链管理机制
本文将结合实战代码,深入探讨 Spring Cloud Gateway 2026.x 中自定义过滤器链的设计与限流熔断策略的实现。
一、环境准备与基础配置
1.1 依赖配置
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-ratelimiter</artifactId>
<version>2.3.0</version>
</dependency>
1.2 基础路由配置
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- StripPrefix=2
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=2
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- PUT
- DELETE
allowedHeaders: "*"
maxAge: 3600
二、自定义过滤器链设计
Spring Cloud Gateway 的过滤器分为 GatewayFilter(针对特定路由)和 GlobalFilter(全局生效)。2026.x 版本增强了过滤器的排序和链式管理能力。
2.1 自定义认证过滤器
@Component
@Order(-100) // 优先级最高,最先执行
public class AuthGlobalFilter implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(AuthGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String token = request.getHeaders().getFirst("Authorization");
// 白名单路径跳过认证
String path = request.getURI().getPath();
if (isWhitelist(path)) {
return chain.filter(exchange);
}
// Token 验证逻辑
if (StringUtils.isEmpty(token) || !token.startsWith("Bearer ")) {
log.warn("未授权访问: {}", path);
return buildUnauthorizedResponse(exchange);
}
try {
// 解析 Token 并验证
Claims claims = JwtUtil.parseToken(token.substring(7));
// 将用户信息放入请求头传递给下游
ServerHttpRequest modifiedRequest = request.mutate()
.header("X-User-Id", claims.getUserId())
.header("X-User-Role", claims.getRole())
.build();
return chain.filter(exchange.mutate()
.request(modifiedRequest)
.build());
} catch (Exception e) {
log.error("Token 验证失败", e);
return buildUnauthorizedResponse(exchange);
}
}
private boolean isWhitelist(String path) {
List<String> whitelist = Arrays.asList(
"/api/auth/login",
"/api/auth/register",
"/api/public/**"
);
return whitelist.stream()
.anyMatch(pattern -> PathMatchUtil.match(pattern, path));
}
private Mono<Void> buildUnauthorizedResponse(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = """
{
"code": 401,
"message": "未授权访问,请先登录",
"data": null
}
""";
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
return response.writeWith(Mono.just(buffer));
}
}
2.2 请求日志过滤器
@Component
@Order(-50)
public class RequestLogFilter implements GlobalFilter {
private static final Logger log = LoggerFactory.getLogger(RequestLogFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String requestId = UUID.randomUUID().toString();
// 记录请求开始时间
exchange.getAttributes().put("startTime", System.currentTimeMillis());
exchange.getAttributes().put("requestId", requestId);
// 记录请求信息
log.info("[{}] 请求开始: {} {} IP: {}",
requestId,
request.getMethod(),
request.getURI().getPath(),
request.getRemoteAddress());
return chain.filter(exchange)
.doFinally(signalType -> {
long startTime = (long) exchange.getAttributes().get("startTime");
long duration = System.currentTimeMillis() - startTime;
ServerHttpResponse response = exchange.getResponse();
log.info("[{}] 请求结束: 状态={} 耗时={}ms",
requestId,
response.getStatusCode(),
duration);
});
}
}
2.3 灰度发布过滤器
@Component
public class GrayReleaseGatewayFilterFactory extends
AbstractGatewayFilterFactory<GrayReleaseGatewayFilterFactory.Config> {
public GrayReleaseGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String userId = request.getHeaders().getFirst("X-User-Id");
// 根据用户ID哈希判断是否走灰度版本
if (StringUtils.isNotEmpty(userId) && isGrayUser(userId, config.getGrayRatio())) {
URI grayUri = UriComponentsBuilder.fromUri(exchange.getAttribute(
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR))
.host(config.getGrayServiceHost())
.build()
.toUri();
exchange.getAttributes().put(
ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR,
grayUri);
log.info("灰度路由: 用户{} 路由到灰度版本 {}", userId, grayUri);
}
return chain.filter(exchange);
};
}
private boolean isGrayUser(String userId, int grayRatio) {
// 使用一致性哈希确保同一用户始终走同一版本
int hash = Math.abs(userId.hashCode()) % 100;
return hash < grayRatio;
}
public static class Config {
private String grayServiceHost;
private int grayRatio = 10; // 默认10%流量
// getters and setters
public String getGrayServiceHost() { return grayServiceHost; }
public void setGrayServiceHost(String grayServiceHost) {
this.grayServiceHost = grayServiceHost;
}
public int getGrayRatio() { return grayRatio; }
public void setGrayRatio(int grayRatio) { this.grayRatio = grayRatio; }
}
}
三、Resilience4j 限流熔断实战
Spring Cloud 2026.x 推荐使用 Resilience4j 作为熔断限流组件,替代已进入维护模式的 Hystrix。
3.1 限流器配置
@Configuration
public class RateLimiterConfig {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> {
// 熔断器配置
CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失败率阈值50%
.slowCallRateThreshold(50) // 慢调用率阈值50%
.slowCallDurationThreshold(Duration.ofSeconds(3)) // 慢调用定义:3s以上
.permittedNumberOfCallsInHalfOpenState(10) // 半开状态允许10次调用
.maxWaitDurationInHalfOpenState(Duration.ofSeconds(10))
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
.slidingWindowSize(100) // 滑动窗口大小
.minimumNumberOfCalls(20) // 最小调用次数
.waitDurationInOpenState(Duration.ofSeconds(30)) // 熔断后等待时间
.build();
// 限流器配置
io.github.resilience4j.ratelimiter.RateLimiterConfig rateLimiterConfig =
io.github.resilience4j.ratelimiter.RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(1)) // 刷新周期
.limitForPeriod(100) // 每个周期允许请求数
.timeoutDuration(Duration.ofMillis(500)) // 超时时间
.build();
TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(5)) // 全局超时5s
.build();
return new Resilience4JConfigBuilder(id)
.circuitBreakerConfig(circuitBreakerConfig)
.rateLimiterConfig(rateLimiterConfig)
.timeLimiterConfig(timeLimiterConfig)
.build();
});
}
}
3.2 自定义限流过滤器
@Component
public class RateLimitFilter implements GlobalFilter, Ordered {
private final RateLimiterRegistry rateLimiterRegistry;
private static final Logger log = LoggerFactory.getLogger(RateLimitFilter.class);
public RateLimitFilter(RateLimiterRegistry rateLimiterRegistry) {
this.rateLimiterRegistry = rateLimiterRegistry;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
String limitKey = StringUtils.isNotEmpty(userId) ? userId : "anonymous";
// 为每个用户创建独立的限流器
RateLimiter rateLimiter = rateLimiterRegistry.rateLimiter("user-" + limitKey,
io.github.resilience4j.ratelimiter.RateLimiterConfig.custom()
.limitForPeriod(50) // 每秒50次请求
.limitRefreshPeriod(Duration.ofSeconds(1))
.build());
if (rateLimiter.acquirePermission()) {
return chain.filter(exchange);
} else {
log.warn("用户{} 请求被限流", limitKey);
return buildRateLimitResponse(exchange);
}
}
private Mono<Void> buildRateLimitResponse(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
response.getHeaders().set("Retry-After", "1");
String body = """
{
"code": 429,
"message": "请求过于频繁,请稍后再试",
"data": null
}
""";
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
return response.writeWith(Mono.just(buffer));
}
@Override
public int getOrder() {
return -80; // 在认证之后执行
}
}
3.3 熔断降级处理
@Component
public class CircuitBreakerFilter implements GatewayFilter, Ordered {
private final ReactiveCircuitBreakerFactory circuitBreakerFactory;
private static final Logger log = LoggerFactory.getLogger(CircuitBreakerFilter.class);
public CircuitBreakerFilter(ReactiveCircuitBreakerFactory circuitBreakerFactory) {
this.circuitBreakerFactory = circuitBreakerFactory;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String routeId = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_PREDICATE_MATCHED_PATH_ATTR);
ReactiveCircuitBreaker circuitBreaker = circuitBreakerFactory.create(
"circuit-breaker-" + routeId);
return circuitBreaker.run(
chain.filter(exchange),
throwable -> {
log.error("服务熔断触发: {}", throwable.getMessage());
return buildFallbackResponse(exchange, throwable);
}
);
}
private Mono<Void> buildFallbackResponse(ServerWebExchange exchange, Throwable throwable) {
ServerHttpResponse response = exchange.getResponse();
HttpStatus status;
String message;
if (throwable instanceof TimeoutException) {
status = HttpStatus.GATEWAY_TIMEOUT;
message = "服务请求超时,请稍后重试";
} else if (throwable instanceof CallNotPermittedException) {
status = HttpStatus.SERVICE_UNAVAILABLE;
message = "服务暂时不可用,已触发熔断保护";
} else {
status = HttpStatus.INTERNAL_SERVER_ERROR;
message = "服务异常,请稍后重试";
}
response.setStatusCode(status);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = String.format("""
{
"code": %d,
"message": "%s",
"data": null
}
""", status.value(), message);
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
return response.writeWith(Mono.just(buffer));
}
@Override
public int getOrder() {
return -20;
}
}
四、过滤器链整合与最佳实践
4.1 过滤器执行顺序配置
| 过滤器 | Order | 说明 |
|---|---|---|
| RequestLogFilter | -100 | 请求日志记录(最先) |
| AuthGlobalFilter | -80 | 认证授权 |
| RateLimitFilter | -50 | 限流控制 |
| GrayReleaseFilter | -30 | 灰度发布路由 |
| CircuitBreakerFilter | -20 | 熔断保护 |
| 默认过滤器 | 0 | Spring Gateway 内置过滤器 |
| 后置过滤器 | 100+ | 响应处理 |
4.2 完整的路由配置示例
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/order/**
filters:
- StripPrefix=2
- name: GrayRelease
args:
grayServiceHost: order-service-gray
grayRatio: 20
- name: CircuitBreaker
args:
name: order-service-circuitbreaker
fallbackUri: forward:/fallback/order
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
五、性能优化建议
5.1 启用 Virtual Threads 支持
spring:
threads:
virtual:
enabled: true # Spring Boot 3.3+ 原生支持虚拟线程
reactor:
scheduler:
virtual-threads: true
5.2 Netty 服务端优化
@Configuration
public class NettyConfig {
@Bean
public NettyServerCustomizer nettyServerCustomizer() {
return httpServer -> httpServer
.tcpConfiguration(tcpServer -> tcpServer
.option(ChannelOption.SO_BACKLOG, 1024)
.option(ChannelOption.SO_REUSEADDR, true)
.option(ChannelOption.TCP_NODELAY, true)
)
.httpRequestDecoder(spec -> spec
.maxInitialLineLength(4096)
.maxHeaderSize(8192)
.maxChunkSize(8192)
);
}
}
总结
本文深入探讨了 Spring Cloud Gateway 2026.x 的核心特性,包括:
- 自定义过滤器链:实现了认证、日志、灰度发布等典型场景的过滤器
- Resilience4j 限流熔断:基于最新版本的 Resilience4j 实现了精细化的限流熔断策略
- 最佳实践:过滤器执行顺序、性能优化配置
Spring Cloud Gateway 2026.x 结合虚拟线程和响应式编程模型,能够更好地支撑高并发场景下的 API 网关需求。在实际生产环境中,建议结合监控系统(如 Prometheus + Grafana)实时观测网关的 QPS、延迟、熔断触发等指标,持续优化配置参数。
参考资料:
- Spring Cloud Gateway 官方文档: https://docs.spring.io/spring-cloud-gateway/reference/
- Resilience4j 官方文档: https://resilience4j.readme.io/
- Spring Cloud 2026.x Release Notes
更多推荐

所有评论(0)