乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 微服务与 Spring Cloud 概述

    • 微服务与 Spring Cloud 概述
  • 第2章 服务注册与发现

    • Eureka 服务注册与发现
    • Consul 服务注册与发现
  • 第3章 客户端负载均衡

    • Ribbon 客户端负载均衡
    • Spring Cloud LoadBalancer
  • 第4章 声明式服务调用

    • Feign 声明式 HTTP 客户端
    • OpenFeign 高级特性与 Spring Cloud 集成
  • 第5章 服务容错与熔断

    • Resilience4j 服务容错与熔断
    • Sentinel 流量控制与熔断降级
  • 第6章 配置中心

    • Spring Cloud Config 配置中心
  • 第7章 API 网关

    • Spring Cloud Gateway 现代化 API 网关
    • Zuul 网关(已进入维护模式)
  • 第8章 消息驱动的微服务

    • Spring Cloud Stream 消息驱动的微服务
  • 第9章 分布式追踪与监控

    • Sleuth + Zipkin 分布式链路追踪
  • 第10章 最佳实践与面试考点

    • Spring Cloud 最佳实践与面试考点

Spring Cloud Gateway 现代化 API 网关

导学

飞翔科技 API 网关选型会议上,白歌在白板上画了一张对比表:

维度Zuul 1.xGateway
线程模型Servlet 阻塞Reactor 非阻塞
内存占用每个连接 1MB+ 线程栈少量 Event Loop 线程
WebSocket不支持原生支持

"Gateway 不仅是 Zuul 的替代品,更是全新一代的 API 网关架构。"白歌说,"它是 Spring 生态中第一个完全响应式的网关。"


定位与问题场景

Spring Cloud Gateway 基于 Spring WebFlux 和 Project Reactor,提供:

  • 路由(Route):将请求转发到目标服务
  • 断言(Predicate):匹配请求条件(路径、Header、参数等)
  • 过滤器(Filter):对请求/响应进行拦截处理

三大核心概念:


Gateway 核心原理

基于 WebFlux 的非阻塞处理

关键区别:整个请求生命周期中,没有线程被阻塞等待 I/O。当等待后端响应时,Event Loop 线程可以处理其他请求。

Route Predicate 工厂

Gateway 内置 11 种 Predicate 工厂,以下是常用类型:

Predicate示例说明
Path- Path=/api/order/**路径匹配
Header- Header=X-version, v2请求头匹配
Method- Method=GET,POSTHTTP 方法
Query- Query=category, electronicsQuery 参数
Host- Host=**.feixiang.comHost 域名
Cookie- Cookie=sessionId, .+Cookie 匹配
Weight- Weight=group1, 80按权重分流(灰度发布)

GatewayFilter 工厂

Filter示例说明
AddRequestHeaderAddRequestHeader=X-User-Id, 123添加请求头
AddResponseHeaderAddResponseHeader=X-Response-Time, 100ms添加响应头
StripPrefixStripPrefix=1去掉一级路径前缀
PrefixPathPrefixPath=/api添加路径前缀
RequestRateLimiter基于 Redis 的令牌桶限流限流
CircuitBreaker集成 Resilience4j 熔断网关层熔断
RetryRetry=3重试

完整示例:飞翔科技 Gateway 网关

场景描述

上线 Gateway 替代 Zuul,实现路由转发、统一认证、限流和灰度发布。

操作前后对比:

维度迁移前(Zuul)迁移后(Gateway)
请求处理阻塞,每请求一线程非阻塞,Event Loop
灰度发布需自定义 FilterWeight Predicate 原生支持
限流需自定义 FilterRequestRateLimiter 开箱即用

步骤一:依赖引入

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Gateway 是 WebFlux 项目,不能引入 spring-boot-starter-web -->

步骤二:基础路由配置(Java DSL)

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRoutes(RouteLocatorBuilder builder) {
        return builder.routes()
            // 路由 1:订单服务
            .route("order-service-route", r -> r
                .path("/api/order/**")
                .filters(f -> f
                    .stripPrefix(1)
                    .addRequestHeader("X-Gateway", "feixiang-gateway")
                )
                .uri("lb://FEIXIANG-ORDER-SERVICE")
            )
            // 路由 2:库存服务
            .route("inventory-service-route", r -> r
                .path("/api/inventory/**")
                .filters(f -> f.stripPrefix(1))
                .uri("lb://FEIXIANG-INVENTORY-SERVICE")
            )
            // 路由 3:灰度发布(80% 流量到 v1,20% 到 v2)
            .route("order-v1", r -> r
                .path("/api/order/**")
                .and().weight("order-group", 80)
                .uri("lb://FEIXIANG-ORDER-SERVICE-V1")
            )
            .route("order-v2", r -> r
                .path("/api/order/**")
                .and().weight("order-group", 20)
                .uri("lb://FEIXIANG-ORDER-SERVICE-V2")
            )
            .build();
    }
}

步骤三:YAML 路由配置

spring:
  cloud:
    gateway:
      routes:
        # 订单服务路由
        - id: order-service
          uri: lb://FEIXIANG-ORDER-SERVICE
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Gateway, feixiang-gateway

        # 库存服务路由
        - id: inventory-service
          uri: lb://FEIXIANG-INVENTORY-SERVICE
          predicates:
            - Path=/api/inventory/**
          filters:
            - StripPrefix=1

        # 灰度发布
        - id: order-v1
          uri: lb://FEIXIANG-ORDER-SERVICE
          predicates:
            - Path=/api/order/**
            - Weight=order-group, 80
        - id: order-v2
          uri: lb://FEIXIANG-ORDER-SERVICE-V2
          predicates:
            - Path=/api/order/**
            - Weight=order-group, 20

步骤四:全局过滤器——统一认证

@Component
@Slf4j
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();

        // 放行登录接口
        if (path.startsWith("/api/auth/login")) {
            return chain.filter(exchange);
        }

        // 校验 Token
        String token = request.getHeaders().getFirst("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            byte[] body = "{\"code\":401,\"message\":\"未授权\"}".getBytes();
            return response.writeWith(
                Mono.just(response.bufferFactory().wrap(body))
            );
        }

        // 传递用户信息到下游
        ServerHttpRequest modifiedRequest = request.mutate()
                .header("X-User-Id", extractUserId(token))
                .build();
        return chain.filter(exchange.mutate().request(modifiedRequest).build());
    }

    @Override
    public int getOrder() {
        return -1;  // 高优先级
    }
}

步骤五:Redis 限流

spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://FEIXIANG-ORDER-SERVICE
          predicates:
            - Path=/api/order/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter:
                  replenishRate: 10      # 每秒生成令牌数
                  burstCapacity: 20      # 令牌桶容量
                key-resolver: "#{@ipKeyResolver}"

  data:
    redis:
      host: localhost
      port: 6379
@Configuration
public class RateLimiterConfig {
    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(
            exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
        );
    }
}

易错场景

1. 引入 spring-boot-starter-web 导致启动失败

Gateway 基于 WebFlux,与 Spring MVC(Servlet)互斥。项目不能同时引入 spring-boot-starter-web 和 spring-cloud-starter-gateway。

报错:Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway

2. lb:// 前缀缺失导致不经过 LoadBalancer

# ❌ 错误:直接写 URL,不走负载均衡和服务发现
uri: http://localhost:8080

# ✅ 正确:lb:// 前缀,走 LoadBalancer
uri: lb://FEIXIANG-ORDER-SERVICE

3. Weight Predicate 未正确配置 group

# ❌ 错误:只有一个路由配了权重,另一个没配,权重路由不生效
# ✅ 正确:同一 group 的多个路由权重和应为 100
- Weight=order-group, 80
- Weight=order-group, 20

4. 过滤器顺序问题

Gateway 中 order 越小优先级越高。认证过滤器应放在最前面(如 order=-1),跨域过滤器也应高优先级。


面试考点

Gateway 和 Zuul 1.x 的核心区别?

Gateway 基于 WebFlux/Reactor 非阻塞架构,使用 Netty 作为底层通信组件,少量 Event Loop 线程处理大量并发;Zuul 1.x 基于 Servlet 阻塞模型,每个请求占用一个线程。Gateway 支持 WebSocket 长连接,Zuul 1.x 不支持。Gateway 的 Predicate(断言)+ Filter(过滤器)机制比 ZuulFilter 更灵活。

Gateway 路由匹配的过程?

  1. RoutePredicateHandlerMapping 遍历所有 Route 定义
  2. 对每个 Route,逐一评估其 Predicate 组合(AND 关系)
  3. 找到第一个完全匹配的 Route,返回给 FilteringWebHandler
  4. FilteringWebHandler 加载该 Route 的 GatewayFilter 和所有 GlobalFilter 组成过滤器链
  5. 按 order 排序后依次执行,最终转发到目标 URI

Gateway 如何实现限流?

内置 RequestRateLimiter GatewayFilter,基于 Redis + 令牌桶算法。replenishRate 控制令牌生成速率,burstCapacity 控制桶容量(允许突发流量)。通过 KeyResolver 定义限流维度:IP、用户 ID、接口路径等。

Gateway 如何实现灰度发布?

Weight Predicate:将流量按权重分配到不同版本的微服务。

- id: v1
  predicates:
    - Path=/api/**
    - Weight=group1, 80
  uri: lb://service-v1
- id: v2
  predicates:
    - Path=/api/**
    - Weight=group1, 20
  uri: lb://service-v2

小结

Spring Cloud Gateway 以响应式架构重新定义了 API 网关,在性能(非阻塞 I/O)、功能(Predicate + Filter)、可扩展性(自定义 GlobalFilter)方面全面超越 Zuul 1.x。内置的限流、熔断、灰度发布能力让网关成为微服务架构的真正"守门人"。下一章我们转向异步通信——Spring Cloud Stream 消息驱动。

下一页
Zuul 网关(已进入维护模式)