Spring Cloud Gateway架构与路由配置
微服务架构中API网关是所有外部请求的统一入口,负责路由转发、认证鉴权、限流熔断和日志审计。Spring Cloud Gateway基于Spring WebFlux构建,采用响应式编程模型,相比传统Servlet架构的Zuul具有更高的并发吞吐能力。
Gateway的核心概念包括Route(路由)、Predicate(断言)和Filter(过滤器)。Route由ID、目标URI、一组Predicate和一组Filter组成,Predicate匹配请求决定路由走向,Filter修改请求和响应。
# application.yml 路由配置
spring:
cloud:
gateway:
routes:
# 用户服务路由
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
- Method=GET,POST
filters:
- StripPrefix=2
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 100
redis-rate-limiter.burstCapacity: 200
# 订单服务路由
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
- Header=Authorization, Bearer .*
filters:
- StripPrefix=2
- AddResponseHeader=X-Gateway-Version, 2.1.0
lb://前缀表示使用负载均衡,Gateway通过服务发现组件(Nacos/Eureka)解析服务名到实际实例地址。StripPrefix=2移除URL前两段路径(/api/users),转发给后端的路径为/users。
自定义过滤器与请求拦截
Gateway提供两种过滤器:Global Filter全局生效,Gateway Filter绑定到特定路由。实际项目中通常通过自定义Global Filter实现认证鉴权、请求日志和跨域处理。
@Component
public class AuthFilter implements GlobalFilter, Ordered {
@Autowired
private JwtUtil jwtUtil;
private static final List<String> WHITELIST = List.of(
"/api/auth/login",
"/api/auth/register",
"/api/auth/refresh"
);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (WHITELIST.stream().anyMatch(path::startsWith)) {
return chain.filter(exchange);
}
String auth = request.getHeaders().getFirst("Authorization");
if (auth == null || !auth.startsWith("Bearer ")) {
return unauthorizedResponse(exchange, "Missing or invalid Authorization header");
}
String token = auth.substring(7);
try {
Claims claims = jwtUtil.parseToken(token);
String userId = claims.getSubject();
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-Id", userId)
.header("X-User-Role", claims.get("role", String.class))
.build();
return chain.filter(exchange.mutate().request(mutatedRequest).build());
} catch (Exception e) {
return unauthorizedResponse(exchange, "Invalid or expired token");
}
}
private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String message) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
String body = String.format("{\"code\":401,\"message\":\"%s\"}", message);
DataBuffer buffer = response.bufferFactory()
.wrap(body.getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer));
}
@Override
public int getOrder() {
return -100;
}
}
getOrder()返回值决定过滤器执行顺序,认证过滤器应设置为高优先级(负数),在限流和日志过滤器之前执行。请求修改通过exchange.mutate()创建新的ServerWebExchange,避免直接修改原始请求对象导致的线程安全问题。
限流策略与熔断配置
高并发设计场景下限流是保护后端服务的关键手段。Gateway内置RequestRateLimiter过滤器,基于Redis令牌桶算法实现分布式限流。令牌桶以固定速率生成令牌,请求消耗令牌,桶满时拒绝新请求。
// 自定义限流KeyResolver - 按用户ID限流
@Configuration
public class RateLimiterConfig {
@Bean
public KeyResolver userKeyResolver() {
return exchange -> {
String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
return Mono.just(userId != null ? userId : "anonymous");
};
}
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
}
// Resilience4j熔断配置
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id ->
new Resilience4JConfigBuilder(id)
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(3))
.build())
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.slowCallRateThreshold(60)
.waitDurationInOpenState(Duration.ofSeconds(30))
.slidingWindowSize(10)
.minimumNumberOfCalls(5)
.build())
.build()
);
}
熔断器的三个状态:Closed(正常)、Open(熔断,拒绝所有请求)、Half-Open(半开,允许少量请求探测恢复)。failureRateThreshold设为50%意味着10次请求中5次失败即触发熔断,waitDurationInOpenState设为30秒表示熔断30秒后进入半开状态。fallbackUri指定熔断后的降级处理路径,返回缓存数据或友好错误提示。
服务治理与动态路由
生产环境需要动态调整路由规则而不重启Gateway。通过Nacos配置中心实现路由动态刷新:
@Component
public class DynamicRouteListener {
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
@NacosConfigListener(dataId = "gateway-routes.json", groupId = "GATEWAY_GROUP")
public void onRouteChange(String config) {
List<RouteDefinition> routes = JSON.parseObject(
config, new TypeReference<List<RouteDefinition>>() {}
);
routes.forEach(route -> {
routeDefinitionWriter.delete(Mono.just(route.getId()));
routeDefinitionWriter.save(Mono.just(route));
});
ApplicationContextHolder.getContext()
.publishEvent(new RefreshRoutesEvent(this));
}
}
动态路由在灰度发布场景中特别有用:新增一条指向新版本服务的路由,通过Header或Cookie匹配将部分流量导入新版本,验证无误后逐步扩大流量比例,实现平滑升级。routeDefinitionWriter是Gateway提供的路由写入接口,配合RefreshRoutesEvent触发路由表刷新,整个过程无需重启服务。
API网关作为微服务架构的流量枢纽,配置复杂度随着服务数量增长而上升。建议将路由配置、限流规则和熔断参数统一存储在配置中心,通过版本管理追踪变更历史。Gateway的JVM参数建议设置-Xmx512m -XX:MaxDirectMemorySize=256m,WebFlux的Netty使用直接内存处理请求,需要单独配置堆外内存上限。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/wei-fu-wu-api-wang-guan-da-jian-springcloudgateway-lu-you/