1. Spring Cloud Gateway 网关基础解析
Spring Cloud Gateway 作为 Spring Cloud 生态中的 API 网关解决方案,本质上是一个反向代理服务,它基于 Reactor 编程模型和 Netty 异步 IO 框架构建。与传统的 Zuul 1.x 相比,它采用了非阻塞式架构,能够更好地处理高并发场景。在实际项目中,我通常会在微服务架构的入口层部署 Gateway,让它承担以下核心职责:
- 路由分发:根据预定义的规则将客户端请求转发到对应的后端服务
- 统一认证:集中处理 JWT 校验、OAuth2 认证等安全逻辑
- 流量控制:通过熔断、限流等机制保护后端服务
- 协议转换:处理 HTTP/HTTPS、gRPC、WebSocket 等不同协议间的转换
提示:生产环境中建议将 Gateway 部署在独立的服务节点,与业务服务物理隔离,避免资源竞争影响网关性能。
1.1 核心架构设计
Gateway 的核心处理流程可以分为三个阶段:
- 路由匹配阶段:通过 Predicate 判断请求是否符合路由规则
- 过滤器链处理:执行预定义的请求/响应过滤器链
- 代理服务调用:通过 Netty 客户端转发请求到目标服务
这种设计模式与 Servlet 规范中的 FilterChain 类似,但采用了响应式编程范式。以下是一个典型的内置过滤器执行顺序示例:
// 过滤器执行顺序示例 GlobalFilter -> GatewayFilter -> NettyRoutingFilter -> NettyWriteResponseFilter在实际开发中,我发现过滤器顺序对业务逻辑有重要影响。比如认证过滤器必须放在链路前端,而日志记录过滤器通常放在靠后位置。
2. 动态路由配置实战
2.1 基础路由配置
Gateway 支持通过 YAML 或 Java DSL 两种方式配置路由。对于中小型项目,我推荐使用 YAML 配置方式,因为它更直观且支持热更新:
spring: cloud: gateway: routes: - id: user_service uri: lb://user-service predicates: - Path=/api/users/** filters: - StripPrefix=1 - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20这个配置实现了:
- 将
/api/users/**的请求路由到 user-service - 移除路径中的第一个前缀(即
/api) - 启用基于 Redis 的限流功能(每秒10个请求,峰值20)
2.2 服务发现集成
当与 Nacos/Eureka 集成时,Gateway 可以实现动态路由发现。这里以 Nacos 为例的关键配置:
<!-- pom.xml 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency># application.yml 配置 spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 gateway: discovery: locator: enabled: true lower-case-service-id: true这种配置下,Gateway 会自动将服务名转换为路由规则。例如服务order-service会自动注册为/order-service/**的路由。
经验:生产环境建议关闭默认的 discovery.locator.enabled,改为显式定义路由规则,避免暴露不必要的服务端点。
3. 高级过滤器开发
3.1 自定义全局过滤器
实现一个记录请求日志的全局过滤器:
@Component @Order(-1) public class LoggingFilter implements GlobalFilter { private static final Logger log = LoggerFactory.getLogger(LoggingFilter.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { long startTime = System.currentTimeMillis(); ServerHttpRequest request = exchange.getRequest(); return chain.filter(exchange).then(Mono.fromRunnable(() -> { long duration = System.currentTimeMillis() - startTime; log.info("{} {} {} - {}ms", request.getMethod(), request.getURI(), exchange.getResponse().getStatusCode(), duration); })); } }这个过滤器会记录每个请求的方法、URI、状态码和耗时,Order 设为 -1 确保它在其他过滤器之前执行。
3.2 业务鉴权过滤器
实现基于 JWT 的权限校验过滤器:
@Component public class AuthFilter implements GatewayFilter, Ordered { private final JwtUtil jwtUtil; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getHeaders().getFirst("Authorization"); if (StringUtils.isEmpty(token)) { return unauthorized(exchange, "Missing token"); } try { Claims claims = jwtUtil.parseToken(token.replace("Bearer ", "")); exchange.getAttributes().put("userId", claims.getSubject()); return chain.filter(exchange); } catch (Exception e) { return unauthorized(exchange, "Invalid token"); } } private Mono<Void> unauthorized(ServerWebExchange exchange, String message) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().writeWith( Mono.just(exchange.getResponse() .bufferFactory() .wrap(message.getBytes())) ); } @Override public int getOrder() { return -100; } }4. 性能优化与生产实践
4.1 线程池配置
Gateway 默认使用 Reactor Netty 的线程模型,可以通过以下配置优化:
server: netty: connection-timeout: 5000 max-initial-line-length: 8192 max-header-size: 32768 max-chunk-size: 8192 max-http-post-size: 2097152 thread: select-count: 4 worker-count: 16对于 CPU 密集型操作(如加解密),建议配置单独的线程池:
@Bean public Scheduler boundedElasticScheduler() { return Schedulers.newBoundedElastic( 16, // 最大线程数 1000, // 任务队列容量 "custom-scheduler" ); }4.2 熔断与限流
集成 Resilience4j 实现熔断:
@Bean public Customizer<ReactiveResilience4JCircuitBreakerFactory> defaultCustomizer() { return factory -> factory.configureDefault(id -> new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(50) .waitDurationInOpenState(Duration.ofMillis(1000)) .slidingWindowSize(10) .build()) .build()); }Redis 限流配置示例:
spring: redis: host: localhost port: 6379 cloud: gateway: routes: - id: rate_limit_route uri: http://example.org predicates: - Path=/api/** filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 100 redis-rate-limiter.burstCapacity: 200 redis-rate-limiter.requestedTokens: 15. 常见问题排查指南
5.1 路由匹配失效
现象:配置的路由规则不生效排查步骤:
- 检查
spring.cloud.gateway.enabled是否为 true - 验证 predicates 配置是否正确(特别注意 Path 的 Ant 风格匹配)
- 查看是否有更高优先级的全局过滤器拦截了请求
5.2 跨域问题处理
推荐配置方式:
@Bean public CorsWebFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsWebFilter(source); }5.3 文件上传问题
Gateway 默认限制文件大小为 256KB,需要调整配置:
spring: webflux: multipart: max-file-size: 10MB max-request-size: 10MB同时需要在路由过滤器中处理文件上传:
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { if (exchange.getRequest().getHeaders().getContentType().includes(MediaType.MULTIPART_FORM_DATA)) { return exchange.getMultipartData() .flatMap(parts -> { // 处理文件部分 return chain.filter(exchange); }); } return chain.filter(exchange); }6. 监控与运维
6.1 指标监控
集成 Actuator 和 Prometheus:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>关键监控端点:
/actuator/gateway/routes- 查看所有路由/actuator/gateway/globalfilters- 查看全局过滤器/actuator/metrics/gateway.requests- 请求指标
6.2 日志收集
建议采用 MDC 记录请求追踪信息:
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String traceId = UUID.randomUUID().toString(); MDC.put("traceId", traceId); exchange.getResponse().getHeaders().add("X-Trace-Id", traceId); return chain.filter(exchange) .doFinally(signalType -> MDC.clear()); }7. 安全加固方案
7.1 常见安全措施
- 禁用敏感端点:
management: endpoint: gateway: enabled: false health: show-details: never- 请求头过滤:
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { exchange.getRequest().mutate() .headers(httpHeaders -> { httpHeaders.remove("X-Forwarded-For"); httpHeaders.remove("X-Real-IP"); }); return chain.filter(exchange); }- IP 白名单:
@Bean public GlobalFilter ipFilter() { return (exchange, chain) -> { String clientIp = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress(); if (!allowIps.contains(clientIp)) { exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); return exchange.getResponse().setComplete(); } return chain.filter(exchange); }; }8. 性能测试数据参考
以下是在 4C8G 云服务器上的基准测试结果(使用 JMeter 压测):
| 并发数 | 平均响应时间 | 吞吐量 | 错误率 |
|---|---|---|---|
| 100 | 23ms | 4200/s | 0% |
| 500 | 56ms | 8800/s | 0% |
| 1000 | 112ms | 9200/s | 0.2% |
| 2000 | 243ms | 9500/s | 1.5% |
优化建议:
- 当并发超过 1000 时,建议增加 Gateway 实例数量
- 响应时间超过 200ms 时,需要检查过滤器链性能
- 错误率上升时,应调整限流和熔断配置
9. 集群部署方案
9.1 基于 Kubernetes 的部署
典型 Deployment 配置:
apiVersion: apps/v1 kind: Deployment metadata: name: gateway spec: replicas: 3 selector: matchLabels: app: gateway template: metadata: labels: app: gateway spec: containers: - name: gateway image: registry.example.com/gateway:1.0.0 ports: - containerPort: 8080 resources: limits: cpu: "2" memory: 2Gi requests: cpu: "1" memory: 1Gi livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 30 periodSeconds: 109.2 配置同步方案
使用 Nacos Config 实现配置中心化:
spring: cloud: nacos: config: server-addr: ${NACOS_HOST:localhost}:8848 file-extension: yaml shared-configs: -># 旧版 spring.cloud.gateway.httpclient.pool.max-connections=500 # 新版 spring.cloud.gateway.httpclient.pool.max-connections=500废弃 API 替换:
RouteLocatorBuilder.routes()替换为RouteLocatorBuilder.builder()WebFilter接口方法签名变更
升级步骤建议:
- 先在测试环境验证兼容性
- 逐步替换废弃 API
- 监控核心指标变化
- 回滚方案准备
在实际项目中,我发现 Gateway 3.x 的内存占用比 2.x 降低了约 15%,特别是在高并发场景下表现更稳定。不过需要注意某些自定义过滤器可能需要适配新的响应式 API。