一、微服务架构中为什么需要API网关?

在微服务架构中,一个系统通常会被拆分为多个独立的微服务。如果客户端直接调用每个微服务的地址,会面临以下问题:

  • 客户端复杂性高:需要维护多个微服务的地址和配置,代码冗余且难以维护。

  • 认证鉴权复杂:每个微服务可能有不同的认证方式,客户端需要适配多种认证逻辑。

  • 跨域与协议问题:存在跨域请求、防火墙限制、浏览器协议兼容性等问题。

  • 系统难以重构:微服务随着项目迭代可能需要重新划分,直接调用会导致调用链重构困难。

API网关应运而生,它作为系统的统一入口,为微服务提供路由转发、认证鉴权、流量控制、监控日志等公共能力,实现业务与非业务逻辑的解耦。


二、Spring Cloud Gateway 是什么?

Spring Cloud Gateway 是 Spring Cloud 官方推出的第二代网关框架,旨在取代 Netflix Zuul。它具有以下特点:

  • 响应式编程:基于 WebFlux + Netty + Reactor 实现,不支持传统的 Servlet 容器。

  • 高性能:官方基准测试显示其性能显著优于 Zuul1 和 Zuul2。

  • 灵活的路由与过滤机制:支持动态路由、断言匹配、过滤器链等核心功能。

官方文档:Spring Cloud Gateway Reference

性能对比(部分数据)

网关类型平均延迟每秒请求数/线程
Spring Cloud Gateway6.61ms3.24k
Zuul112.56ms2.09k
Zuul22.09ms11.77k

三、Spring Cloud Gateway 核心概念

3.1 路由(Route)

路由是网关中最基本的单元,包含:

  • ID:唯一标识

  • URI:目标服务地址

  • Predicates:断言条件

  • Filters:过滤器链

3.2 断言(Predicates)

基于 Java 8 的 Predicate<ServerWebExchange>,用于匹配 HTTP 请求的各个部分(如路径、请求头、参数等)。匹配成功则路由生效。

3.3 过滤器(Filter)

分为两类:

  • GatewayFilter:作用于特定路由

  • GlobalFilter:全局生效,作用于所有路由


四、Spring Cloud Gateway 工作原理

text

客户端请求 → 网关路由匹配 → 执行Pre过滤器链 → 转发至目标服务 → 执行Post过滤器链 → 返回响应

过滤器分为 pre 和 post 两种:

  • pre过滤器:在转发前执行(如鉴权、添加请求头)

  • post过滤器:在收到响应后执行(如日志记录、修改响应)


五、Spring Cloud Gateway 实战详解

5.1 快速接入

1)引入依赖

xml

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>

注意:Gateway 与 spring-webmvc 冲突,需排除后者。

2)配置文件示例

yaml

spring:
  application:
    name: mall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      routes:
        - id: order_route
          uri: lb://mall-order
          predicates:
            - Path=/order/**
        - id: user_route
          uri: lb://mall-user
          predicates:
            - Path=/user/**
3)测试访问

text

http://localhost:8888/order/findOrderByUserId/1

5.2 路由断言工厂(Predicate Factories)

5.2.1 路径匹配

yaml

predicates:
  - Path=/order/**
5.2.2 Header 匹配

yaml

predicates:
  - Header=X-Request-Id, \d+

请求头 X-Request-Id 的值必须为数字。

5.3 过滤器工厂(GatewayFilter Factories)

5.3.1 添加请求头

yaml

filters:
  - AddRequestHeader=X-Request-color, red
5.3.2 添加请求参数

yaml

filters:
  - AddRequestParameter=color, blue
5.3.3 自定义过滤器工厂

java

@Component
public class CheckAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return (exchange, chain) -> {
            log.info("调用自定义过滤器:{} = {}", config.getName(), config.getValue());
            return chain.filter(exchange);
        };
    }
}

配置使用:

yaml

filters:
  - CheckAuth=fox,男

5.4 全局过滤器(Global Filters)

5.4.1 负载均衡过滤器

ReactiveLoadBalancerClientFilter 负责将 lb://service 转换为实际的服务地址。

5.4.2 自定义全局过滤器(实现鉴权)

java

@Component
public class CheckAuthFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("token");
        if (token == null) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // TODO: 校验token
        return chain.filter(exchange);
    }
    
    @Override
    public int getOrder() {
        return 2;
    }
}

5.5 跨域配置(CORS)

YAML 配置方式

yaml

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowed-origins: "*"
            allowed-methods: "*"
Java 配置方式

java

@Bean
public CorsWebFilter corsFilter() {
    CorsConfiguration config = new CorsConfiguration();
    config.addAllowedOrigin("*");
    config.addAllowedMethod("*");
    config.addAllowedHeader("*");
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
    source.registerCorsConfiguration("/**", config);
    
    return new CorsWebFilter(source);
}

5.6 基于 Redis + Lua 的限流

1)引入依赖

xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2)配置限流过滤器

yaml

filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 1   # 令牌桶每秒填充速率
      redis-rate-limiter.burstCapacity: 2   # 令牌桶总容量
      key-resolver: "#{@keyResolver}"       # 限流键解析器
3)定义 KeyResolver

java

@Bean
KeyResolver keyResolver() {
    // URL 限流
    return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
    // 参数限流
    // return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

5.7 整合 Sentinel 实现网关限流

1)引入依赖

xml

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2)配置 Sentinel Dashboard

yaml

spring:
  cloud:
    sentinel:
      transport:
        dashboard: 127.0.0.1:8080
3)Sentinel 网关流控原理

Sentinel 将网关流控规则转换为热点参数规则,通过 GatewayFlowSlot 进行规则检查,支持:

  • 路由维度限流:基于 routeId

  • API 分组维度限流:用户自定义分组

注:Spring Boot 3 + Spring Cloud Gateway 与 Sentinel 的兼容性待官方更新。


六、总结与建议

Spring Cloud Gateway 作为 Spring Cloud 生态中的第二代网关,具有响应式、高性能、易扩展等优点,适合作为微服务架构的统一入口。

最佳实践建议:

  1. 路由配置集中管理:结合配置中心(如 Nacos)实现动态路由。

  2. 过滤器链合理设计:区分业务过滤器与通用过滤器,保持职责单一。

  3. 限流与熔断结合使用:搭配 Sentinel 或 Resilience4j 实现系统保护。

  4. 监控与日志完备:集成 Micrometer + Prometheus + Grafana 实现全方位监控。


七、参考资料

更多推荐