Spring Cloud Gateway是Spring生态的API网关组件,基于Spring WebFlux和Project Reactor构建,提供路由转发、请求过滤、限流熔断等核心能力。相比Zuul 1.x的Servlet阻塞模型,Gateway采用Netty非阻塞模型,在高并发场景下吞吐量优势显著。本文从路由配置到自定义过滤器,完整演示Spring Cloud Gateway的生产级配置。
Gateway架构与核心组件解析
Spring Cloud Gateway的架构由三个核心组件构成:Route(路由)由ID、目标URI、Predicate断言和Filter过滤器组成;Predicate断言匹配HTTP请求的任意属性(Path、Method、Header、Query参数等),匹配成功则走该路由;Filter过滤器在请求转发前后对请求和响应进行修改处理。
请求处理流程:客户端请求到达Gateway后,GatewayHandlerMapping根据Predicate匹配路由,匹配到的路由经过Filter链处理(pre阶段),然后通过ProxyFilter转发到后端服务,响应返回再经过Filter链(post阶段)返回客户端。
项目搭建与依赖配置
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
路由断言Predicate配置方式
Gateway支持配置文件方式和编程方式定义路由。YAML配置方式直观易维护:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
- Method=GET,POST
- Header=X-Request-Source, ^(web|mobile)$
filters:
- StripPrefix=2
- AddResponseHeader=X-Gateway-Version, 1.0
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
- Query=userId, \d+
filters:
- StripPrefix=2
- id: time-route
uri: lb://maintenance-service
predicates:
- Between=2026-08-15T00:00:00+08:00, 2026-08-15T06:00:00+08:00
lb://前缀表示使用服务发现(如Nacos、Eureka)负载均衡,Gateway通过Spring Cloud LoadBalancer选择后端实例。StripPrefix=2表示转发前去掉URL前两级路径,如/api/users/list变为/list。断言支持组合使用,多个断言间为AND关系。
编程式动态路由与Redis存储
配置文件方式修改路由需要重启网关。生产环境需要运行时动态增删路由,通过RouteLocator编程式定义配合Redis持久化:
@Configuration
public class DynamicRouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r
.path("/api/users/**")
.filters(f -> f
.stripPrefix(2)
.requestRateLimiter(config -> config
.setRedisRateLimiter(redisRateLimiter())
.setKeyResolver(userKeyResolver())
)
)
.uri("lb://user-service"))
.build();
}
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getHeaders().getFirst("X-User-Id") != null
? exchange.getRequest().getHeaders().getFirst("X-User-Id")
: exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
@Bean
RedisRateLimiter redisRateLimiter() {
// defaultReplenishRate: 每秒令牌填充数
// defaultBurstCapacity: 令牌桶容量
return new RedisRateLimiter(100, 200);
}
}
运行时动态添加路由通过RouteDefinitionWriter和RouteDefinitionRepository实现,配合Redis持久化路由定义:
@RestController
@RequestMapping("/gateway/routes")
public class RouteController {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@Autowired
private RouteDefinitionLocator routeDefinitionLocator;
@PostMapping
public Mono addRoute(@RequestBody RouteDefinition definition) {
return routeDefinitionWriter.save(Mono.just(definition))
.then(Mono.just("Route added: " + definition.getId()));
}
@DeleteMapping("/{id}")
public Mono deleteRoute(@PathVariable String id) {
return routeDefinitionWriter.delete(Mono.just(id))
.then(Mono.just("Route deleted: " + id));
}
}
限流过滤器与Redis令牌桶算法
RequestRateLimiter过滤器底层使用Redis + Lua脚本实现令牌桶限流算法。令牌桶参数:replenishRate(令牌填充速率,每秒生成多少令牌)和burstCapacity(桶最大容量)。实际QPS上限由两者共同决定——稳定QPS等于replenishRate,突发QPS上限等于burstCapacity。
spring:
cloud:
gateway:
routes:
- id: api-limited
uri: lb://backend-service
predicates:
- Path=/api/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 50
redis-rate-limiter.burstCapacity: 100
key-resolver: "#{@ipKeyResolver}"
KeyResolver决定限流维度——按IP限流、按用户限流、按接口限流。按IP限流的KeyResolver:
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
超出限流阈值的请求返回HTTP 429 Too Many Requests。可自定义返回体:
@Bean
public GatewayFilter customRateLimitFilter() {
return (exchange, chain) -> {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = "{\"code\":429,\"message\":\"请求过于频繁,请稍后重试\"}";
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
return response.writeWith(Mono.just(buffer));
};
}
熔断降级与Resilience4j集成
Gateway集成Resilience4j实现熔断降级,后端服务异常时自动短路返回降级响应:
spring:
cloud:
gateway:
routes:
- id: circuit-breaker-route
uri: lb://backend-service
predicates:
- Path=/api/**
filters:
- name: CircuitBreaker
args:
name: backendCircuit
fallbackUri: forward:/fallback
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
timelimiter:
configs:
default:
timeoutDuration: 5s
fallbackUri指向网关内的降级处理接口,熔断触发时转发到该接口返回预设响应:
@RestController
public class FallbackController {
@GetMapping("/fallback")
public Mono
slidingWindowSize=10表示滑动窗口统计10次调用,failureRateThreshold=50表示失败率达到50%时熔断器打开,waitDurationInOpenState=10s表示熔断打开10秒后进入半开状态试探恢复。timeoutDuration=5s为超时阈值,请求超过5秒未返回视为失败。
全局过滤器与跨域CORS配置
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
private static final List WHITE_LIST = List.of(
"/api/auth/login", "/api/auth/register"
);
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
// 白名单放行
if (WHITE_LIST.stream().anyMatch(path::startsWith)) {
return chain.filter(exchange);
}
String token = request.getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
return onError(exchange, "Missing or invalid token", HttpStatus.UNAUTHORIZED);
}
// 添加用户信息到请求头,传递给后端服务
String userId = validateToken(token.substring(7));
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-Id", userId)
.build();
return chain.filter(exchange.mutate().request(mutatedRequest).build());
}
@Override
public int getOrder() {
return -100; // 优先级最高
}
private Mono onError(ServerWebExchange exchange, String message, HttpStatus status) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(status);
return response.setComplete();
}
}
CORS全局配置:
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOriginPatterns(List.of("*"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
config.setAllowedHeaders(List.of("*"));
config.setAllowCredentials(true);
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springcloudgateway-dong-tai-lu-you-pei-zhi-yu-xian-liu-rong/