文章目录
前言
在微服务架构中,API 网关扮演着流量入口的核心角色。它不仅需要高效路由请求,还要承担安全防护、流量治理、协议转换等关键职责。Spring Cloud Gateway 作为 Spring Cloud 生态的官方网关组件,凭借其 高性能、响应式编程模型 和 高度可扩展性,已成为众多企业构建微服务架构的首选。
然而,随着业务复杂度的提升,开发者往往会面临以下挑战:
- 如何快速响应动态路由需求?
- 怎样统一管理跨服务的认证与日志?
- 能否低成本实现业务定制化逻辑?
这些问题的答案,都藏在 Spring Cloud Gateway 的 扩展点设计 中。
一、为什么需要扩展 Spring Cloud Gateway?
Spring Cloud Gateway 作为 Spring Cloud 生态的 API 网关组件,默认提供了路由转发、负载均衡、限流熔断等核心能力。但在实际生产环境中,业务场景往往更加复杂,开发者通常需要基于以下需求进行扩展:
- 定制路由规则:默认路由配置无法满足动态路由、灰度发布等高级需求。
- 统一认证与授权:需要全局拦截请求,集成 JWT、OAuth2 等安全协议。
- 业务逻辑处理:如请求参数校验、响应体修改、接口耗时统计等。
- 监控与日志:记录请求链路日志,集成 Prometheus 监控指标。
- 适配遗留系统:兼容老系统协议转换(如 SOAP → REST)。
二、Spring Cloud Gateway 核心扩展点
Spring Cloud Gateway 提供了丰富的扩展接口,以下是 5 大核心扩展点:
扩展点 | 作用域 | 典型场景 |
---|---|---|
GlobalFilter | 全局 | 认证、日志、限流 |
GatewayFilter | 路由级别 | 修改请求头、重试策略 |
RoutePredicateFactory | 路由匹配 | 自定义路由条件(如IP白名单) |
RouteLocator | 路由加载 | 动态路由(如数据库配置) |
自定义异常处理 | 全局/路由 | 统一异常响应格式 |
三、扩展点实战:代码与配置详解
3.1 全局过滤器(GlobalFilter)
场景: 记录请求耗时与状态码。
@Component
public class RequestLoggingGlobalFilter implements GlobalFilter, Ordered {
private static final Logger LOG = LoggerFactory.getLogger(RequestLoggingGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
String path = exchange.getRequest().getPath().toString();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long duration = System.currentTimeMillis() - startTime;
int statusCode = exchange.getResponse().getStatusCode() != null
? exchange.getResponse().getStatusCode().value()
: 500;
LOG.info("Path: {} | Status: {} | Time: {}ms", path, statusCode, duration);
}));
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE; // 最后执行
}
}
3.2 路由过滤器(GatewayFilter)
场景: 为特定路由添加自定义请求头。
步骤1:实现 GatewayFilterFactory
@Component
public class AddHeaderGatewayFilterFactory extends AbstractGatewayFilterFactory<AddHeaderGatewayFilterFactory.Config> {
public AddHeaderGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest().mutate()
.header(config.getHeaderName(), config.getHeaderValue())
.build();
return chain.filter(exchange.mutate().request(request).build());
};
}
public static class Config {
private String headerName;
private String headerValue;
// Getter & Setter
}
}
步骤2:配置路由
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- AddHeader=X-Custom-Header, HelloGateway
2.3 自定义路由断言(RoutePredicateFactory)
场景: 仅允许特定 IP 访问管理接口。
@Component
public class IpAllowPredicateFactory extends AbstractRoutePredicateFactory<IpAllowPredicateFactory.Config> {
public IpAllowPredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
return config.getAllowedIps().contains(clientIp);
};
}
public static class Config {
private List<String> allowedIps;
// Getter & Setter
}
}
配置示例:
routes:
- id: admin-route
uri: lb://admin-service
predicates:
- Path=/admin/**
- IpAllow=192.168.1.100, 192.168.1.101
3.4 动态路由(RouteLocator)
场景: 从数据库加载路由配置。
@Bean
public RouteLocator dynamicRouteLocator(RouteDefinitionLocator locator) {
return new RouteLocator() {
@Override
public Flux<Route> getRoutes() {
return locator.getRouteDefinitions()
.flatMap(routeDefinition -> {
// 从数据库查询动态规则
RouteDefinition updatedDef = queryDynamicRules(routeDefinition.getId());
return RouteDefinitionRouteLocator.loadRoute(updatedDef);
});
}
};
}
3.5 自定义异常处理
场景: 统一返回 JSON 格式错误信息。
@Bean
public ErrorWebExceptionHandler customExceptionHandler() {
return new DefaultErrorWebExceptionHandler() {
@Override
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
// 1. 获取原始异常
Throwable error = getError(request);
// 2. 构建标准化响应体
Map<String, Object> body = Map.of(
"code": 500,
"message": error.getMessage(),
"timestamp": Instant.now()
);
// 3. 返回JSON格式响应
return ServerResponse.status(500)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(body);
}
};
}
四、扩展实践注意事项
- 执行顺序:通过 @Order 或实现 Ordered 接口控制过滤器执行顺序。
- 性能影响:避免在过滤器中执行阻塞操作(如同步数据库调用),推荐响应式编程。
- 配置热更新:结合 Spring Cloud Bus 实现动态配置刷新。
- 测试策略:使用 WebTestClient 编写单元测试验证过滤器逻辑。
总结
通过灵活运用 Spring Cloud Gateway 的扩展点,开发者可以轻松实现 路由定制化、业务逻辑增强 和 系统可观测性 等高级功能。本文提供的代码示例与配置可直接应用于生产环境,建议根据实际需求调整细节,并利用监控工具(如 Grafana)持续优化网关性能。