1. Spring Cloud Gateway 是什么?
Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的网关服务。作为 Spring Cloud 生态系统中的网关组件,它旨在为微服务架构提供一种简单而有效的方式来路由到 API,并为它们提供跨领域的关注点,如:安全性、监控/指标和弹性。
提示:与 Zuul 1.x 相比,Spring Cloud Gateway 使用了非阻塞式的 API,性能更好,特别适合高并发场景。
我在实际项目中使用 Spring Cloud Gateway 已经两年多,它最让我惊喜的是其简洁的配置方式和强大的扩展能力。通过简单的 YAML 配置就能实现复杂的路由规则,而自定义过滤器又让它可以灵活应对各种业务场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心特性解析
2.1 路由(Route)机制
路由是网关最基础也是最重要的功能。Spring Cloud Gateway 的路由配置非常直观:
yaml复制spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=2
这段配置表示:
- 所有访问
/api/users/**的请求 - 会被转发到名为
user-service的服务 - 并且去掉路径中的前两级(
/api/users)
2.2 断言(Predicate)
断言决定了请求是否匹配当前路由。Spring Cloud Gateway 内置了多种断言工厂:
- Path 路由断言:最常用的断言,基于路径匹配
- Method 路由断言:基于 HTTP 方法(GET/POST等)
- Header 路由断言:检查请求头
- Cookie 路由断言:检查 Cookie
- Query 路由断言:检查查询参数
- Host 路由断言:基于主机名
- RemoteAddr 路由断言:基于客户端 IP
2.3 过滤器(Filter)
过滤器可以在请求被路由前或后对请求和响应进行修改。过滤器分为两种:
- GatewayFilter:作用于单个路由
- GlobalFilter:作用于所有路由
常见的内置过滤器:
| 过滤器名称 | 功能描述 |
|---|---|
| AddRequestHeader | 添加请求头 |
| AddRequestParameter | 添加请求参数 |
| AddResponseHeader | 添加响应头 |
| PrefixPath | 添加路径前缀 |
| StripPrefix | 去除路径前缀 |
| Retry | 重试机制 |
| CircuitBreaker | 熔断器 |
3. 性能优化实战
3.1 响应式编程模型
Spring Cloud Gateway 基于 Project Reactor 实现了响应式编程模型。这意味着:
- 非阻塞 I/O:可以处理更多并发连接
- 背压支持:防止生产者压垮消费者
- 更少的线程开销:相比传统 Servlet 容器
在实际压力测试中,同样的硬件配置下,Spring Cloud Gateway 的吞吐量是 Zuul 1.x 的 3-5 倍。
3.2 连接池优化
对于下游服务的 HTTP 调用,合理配置连接池非常重要:
yaml复制spring:
cloud:
gateway:
httpclient:
pool:
max-connections: 1000 # 最大连接数
max-idle-time: 30000 # 最大空闲时间(ms)
注意:连接池大小需要根据实际业务量和服务器配置进行调整。过小会导致请求排队,过大会消耗过多资源。
3.3 缓存配置
对于频繁访问的静态资源,可以启用响应缓存:
java复制@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("cache_route", r -> r.path("/static/**")
.filters(f -> f.cache(
CacheConfig.of("staticCache", 60, TimeUnit.SECONDS)))
.uri("http://static-service"))
.build();
}
4. 安全防护策略
4.1 JWT 认证集成
在微服务架构中,通常使用 JWT 进行认证。我们可以通过自定义过滤器实现:
java复制public class JwtAuthenticationFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest()
.getHeaders()
.getFirst(HttpHeaders.AUTHORIZATION);
if (token != null && validateToken(token)) {
return chain.filter(exchange);
}
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
private boolean validateToken(String token) {
// 实现JWT验证逻辑
}
}
4.2 限流保护
防止恶意请求或突发流量打垮系统:
java复制@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
@Bean
public RedisRateLimiter redisRateLimiter() {
return new RedisRateLimiter(10, 20); // 每秒10个请求,突发20个
}
然后在路由配置中应用限流:
yaml复制spring:
cloud:
gateway:
routes:
- id: rate-limited
uri: lb://protected-service
predicates:
- Path=/api/protected/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@ipKeyResolver}"
4.3 CSRF 防护
对于有状态的 Web 应用,需要启用 CSRF 防护:
java复制@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.csrf().csrfTokenRepository(CookieServerCsrfTokenRepository.withHttpOnlyFalse())
.and()
.build();
}
5. 监控与日志
5.1 Actuator 集成
Spring Boot Actuator 提供了丰富的监控端点:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,gateway
endpoint:
health:
show-details: always
访问 /actuator/gateway/routes 可以查看所有路由信息。
5.2 Prometheus 监控
集成 Prometheus 进行指标收集:
xml复制<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
配置:
yaml复制management:
metrics:
export:
prometheus:
enabled: true
5.3 请求日志
自定义过滤器记录请求日志:
java复制public class LoggingFilter implements GlobalFilter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
long startTime = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
long duration = System.currentTimeMillis() - startTime;
logger.info("{} {} {} {}ms",
exchange.getRequest().getMethod(),
exchange.getRequest().getPath(),
exchange.getResponse().getStatusCode(),
duration);
}));
}
}
6. 常见问题与解决方案
6.1 路由匹配顺序问题
Spring Cloud Gateway 的路由匹配是按照配置顺序进行的。如果两个路由的断言都匹配同一个请求,先配置的路由会优先匹配。
解决方案:
- 将更具体的路由放在前面
- 使用
order属性显式指定顺序
6.2 服务发现集成
当使用服务发现(如 Eureka)时,URI 需要使用 lb:// 前缀:
yaml复制uri: lb://user-service
常见问题:
- 服务名大小写敏感
- 服务未注册到发现服务器
- 网络分区导致服务不可见
6.3 超时设置
合理设置各种超时:
yaml复制spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5s
6.4 文件上传问题
大文件上传时需要注意:
- 调整最大请求大小
- 可能需要禁用某些过滤器
- 考虑使用分片上传
配置示例:
yaml复制spring:
webflux:
max-in-memory-size: 10MB
max-request-size: 50MB
7. 高级特性与自定义开发
7.1 自定义断言工厂
实现 RoutePredicateFactory 接口创建自定义断言:
java复制@Component
public class CustomPredicateFactory extends AbstractRoutePredicateFactory<CustomPredicateFactory.Config> {
public CustomPredicateFactory() {
super(Config.class);
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
// 自定义断言逻辑
return true;
};
}
public static class Config {
// 配置属性
}
}
7.2 自定义全局过滤器
实现 GlobalFilter 接口创建全局过滤器:
java复制@Component
@Order(-1) // 执行顺序
public class CustomGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 前置处理
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 后置处理
}));
}
}
7.3 动态路由
通过编程方式动态添加/删除路由:
java复制@Autowired
private RouteDefinitionLocator routeDefinitionLocator;
@Autowired
private RouteDefinitionWriter routeDefinitionWriter;
public void addRoute(String id, String path, String uri) {
RouteDefinition definition = new RouteDefinition();
definition.setId(id);
definition.setUri(URI.create(uri));
PredicateDefinition predicate = new PredicateDefinition("Path=" + path);
definition.setPredicates(Collections.singletonList(predicate));
routeDefinitionWriter.save(Mono.just(definition)).subscribe();
}
8. 生产环境最佳实践
8.1 高可用部署
- 至少部署 2 个网关实例
- 使用负载均衡器(如 Nginx)分发流量
- 配置健康检查
- 考虑跨可用区部署
8.2 配置管理
- 将配置外部化(如使用 Config Server)
- 区分环境(dev/test/prod)
- 使用配置加密保护敏感信息
- 实现配置的热更新
8.3 性能调优
- JVM 参数优化
- 合理设置线程池大小
- 启用响应压缩
- 监控关键指标(QPS、延迟、错误率)
8.4 灾难恢复
- 制定回滚策略
- 准备备用网关配置
- 实现流量切换机制
- 定期演练故障场景
我在实际项目中遇到过网关配置错误导致服务不可用的情况,后来我们建立了严格的配置审查流程和灰度发布机制,显著提高了系统稳定性。
