构建 Spring Cloud Gateway:作为 API 网关,实现路由、过滤、限流、熔断等功能。

各位看官,大家好!我是你们的老朋友,人称“代码界段子手”的程序猿阿Q。今天,咱们不聊鸡汤,也不谈情怀,就来聊聊真刀真枪的技术——如何用 Spring Cloud Gateway 打造一个炫酷的 API 网关!

🚀 准备好了吗?咱们这就开讲!

一、什么是 API 网关?为什么要用它?(别急,先打个比方)

想象一下,你开了一家豪华餐厅,但是厨房、服务员、收银台都藏在深闺之中,顾客进门后一脸懵逼,不知道该往哪走,甚至连菜单都找不到。这时候,你就需要一个专业的“门房”(API 网关),负责:

  • 路由引导: 将顾客带到对应的餐桌(不同的服务)。
  • 菜单展示: 提供统一的 API 接口,让顾客一目了然。
  • 安全检查: 拦住那些想吃霸王餐的家伙(认证和授权)。
  • 人流控制: 限制排队人数,避免餐厅拥堵(限流)。
  • 紧急预案: 厨房着火了,赶紧换一家餐厅(熔断)。

看到了吧?API 网关就像餐厅的门房一样,是整个微服务架构的入口,负责管理和保护你的后端服务。

为什么要用它呢?理由如下:

  • 统一入口: 客户端只需访问网关,无需知道后端服务的具体地址,简化了客户端的开发。
  • 解耦: 网关屏蔽了后端服务的变化,客户端无需关心服务内部的实现细节,降低了耦合度。
  • 安全: 网关可以集中处理认证、授权等安全问题,保护后端服务免受恶意攻击。
  • 监控: 网关可以记录所有请求的日志,方便进行性能分析和故障排查。
  • 扩展性: 网关可以轻松扩展各种功能,如限流、熔断、监控等,提高系统的可用性和可维护性。

二、Spring Cloud Gateway:你的不二之选!

Spring Cloud Gateway 是 Spring 官方提供的 API 网关,基于 Spring WebFlux 和 Project Reactor 构建,具有高性能、高并发、易扩展等特点。

它的优点如下:

  • Spring 全家桶: 无缝集成 Spring Cloud 生态系统,使用方便。
  • 响应式编程: 基于 Reactor 框架,性能更高,吞吐量更大。
  • 动态路由: 支持多种路由方式,可以根据请求的 Header、Path、Query 参数等进行路由。
  • 丰富的过滤器: 提供了大量的内置过滤器,可以实现各种功能,如认证、授权、限流、熔断等。
  • 易于扩展: 可以自定义过滤器和路由策略,满足各种业务需求。

三、手把手教你搭建 Spring Cloud Gateway(代码说话,简单粗暴!)

  1. 创建 Spring Boot 项目:

    使用 Spring Initializr (start.spring.io) 创建一个 Spring Boot 项目,添加以下依赖:

    • spring-cloud-starter-gateway
    • spring-boot-starter-webflux
    • spring-cloud-starter-netflix-eureka-client (如果使用 Eureka 注册中心)
  2. 配置 application.yml:

    server:
      port: 8080 # 网关端口
    
    spring:
      application:
        name: api-gateway # 应用名称
      cloud:
        gateway:
          routes:
            - id: user-service # 路由 ID,自定义
              uri: lb://user-service # 目标服务地址,使用 Eureka 服务名
              predicates: # 路由断言,满足条件才路由
                - Path=/user/** # 匹配 /user 开头的路径
              filters: # 过滤器,对请求进行处理
                - AddRequestHeader=X-Request-Id, ${random.uuid} # 添加请求头
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/ # Eureka 注册中心地址

    解释一下这段配置:

    • server.port: 指定网关的端口号。
    • spring.application.name: 指定应用名称,方便在 Eureka 中注册。
    • spring.cloud.gateway.routes: 配置路由规则,可以配置多个路由。
      • id: 路由的唯一标识符。
      • uri: 目标服务的地址,lb:// 表示使用负载均衡,user-service 是 Eureka 中注册的服务名称。
      • predicates: 路由断言,用于判断请求是否符合路由规则。
        • Path=/user/**: 表示匹配所有以 /user 开头的路径。
      • filters: 过滤器,用于对请求进行处理。
        • AddRequestHeader=X-Request-Id, ${random.uuid}: 表示添加一个名为 X-Request-Id 的请求头,值为一个随机 UUID。
  3. 启动 Eureka 注册中心:

    如果使用了 Eureka,需要先启动 Eureka 注册中心,将后端服务注册到 Eureka 中。

  4. 启动后端服务:

    启动你的后端服务,例如 user-service,并将其注册到 Eureka 中。

  5. 测试:

    访问 http://localhost:8080/user/123,如果配置正确,网关会将请求转发到 user-service,并返回相应的结果。

    🎉 恭喜你,第一个简单的 API 网关已经搭建完成!

四、进阶:路由、过滤、限流、熔断,一个都不能少!

  1. 路由:花样百出,随你挑选!

    Spring Cloud Gateway 提供了多种路由方式,可以根据不同的需求进行配置。

    • Path 路由: 根据请求路径进行路由。

      - id: path-route
        uri: http://example.com
        predicates:
          - Path=/foo/{segment}
    • Method 路由: 根据请求方法进行路由。

      - id: method-route
        uri: http://example.com
        predicates:
          - Method=GET,POST
    • Query 路由: 根据请求参数进行路由。

      - id: query-route
        uri: http://example.com
        predicates:
          - Query=baz,ba.*
    • Header 路由: 根据请求头进行路由。

      - id: header-route
        uri: http://example.com
        predicates:
          - Header=X-Request-Id
    • Host 路由: 根据请求 Host 进行路由。

      - id: host-route
        uri: http://example.com
        predicates:
          - Host=*.example.com
    • After 路由: 指定日期之后才生效的路由。

      - id: after-route
        uri: http://example.com
        predicates:
          - After=2023-12-31T23:59:59+08:00[Asia/Shanghai]
    • 自定义路由: 你可以自定义 Predicate 实现复杂的路由逻辑。

  2. 过滤:请求的美容师和保安!

    过滤器是 Spring Cloud Gateway 的核心组件,可以对请求进行各种处理,例如添加请求头、修改请求参数、验证用户身份等。

    • 内置过滤器: Spring Cloud Gateway 提供了大量的内置过滤器,可以直接使用。

      过滤器 功能
      AddRequestHeader 添加请求头。
      AddRequestParameter 添加请求参数。
      AddResponseHeader 添加响应头。
      RewritePath 重写请求路径。
      StripPrefix 移除请求路径的前缀。
      RequestRateLimiter 限流。
      Hystrix 熔断。
      Token Relay 中继 OAuth 2.0 的访问令牌到下游服务。
      还有很多,等着你去探索!
    • 全局过滤器: 对所有路由生效的过滤器。可以通过实现 GlobalFilter 接口来创建全局过滤器。

      @Component
      public class LoggingGlobalFilter implements GlobalFilter, Ordered {
          private static final Logger logger = LoggerFactory.getLogger(LoggingGlobalFilter.class);
      
          @Override
          public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
              logger.info("Request Path: {}", exchange.getRequest().getPath());
              return chain.filter(exchange);
          }
      
          @Override
          public int getOrder() {
              return 0; // 设置优先级,数字越小优先级越高
          }
      }
    • 自定义过滤器: 你可以自定义 GatewayFilterFactory 实现更复杂的过滤器逻辑。

      @Component
      public class CustomFilterGatewayFilterFactory extends AbstractGatewayFilterFactory<CustomFilterGatewayFilterFactory.Config> {
      
          public CustomFilterGatewayFilterFactory() {
              super(Config.class);
          }
      
          @Override
          public GatewayFilter apply(Config config) {
              return (exchange, chain) -> {
                  // 在请求前执行的代码
                  System.out.println("Custom Filter: " + config.getMessage());
      
                  return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                      // 在响应后执行的代码
                      System.out.println("Custom Filter Post: " + config.getMessage());
                  }));
              };
          }
      
          @Validated
          public static class Config {
              @NotEmpty
              private String message;
      
              public String getMessage() {
                  return message;
              }
      
              public void setMessage(String message) {
                  this.message = message;
              }
          }
      }

      使用:

      spring:
        cloud:
          gateway:
            routes:
              - id: custom-filter-route
                uri: http://example.com
                predicates:
                  - Path=/custom
                filters:
                  - CustomFilter=Hello, Custom Filter!
  3. 限流:控制流量,保护服务!

    限流是指限制单位时间内请求的数量,防止服务被过多的请求压垮。Spring Cloud Gateway 提供了 RequestRateLimiter 过滤器来实现限流。

    • 基于令牌桶算法的限流:

      spring:
        cloud:
          gateway:
            routes:
              - id: rate-limit-route
                uri: lb://user-service
                predicates:
                  - Path=/user/**
                filters:
                  - RequestRateLimiter=true, replenishRate:10, burstCapacity:20 # 每秒填充 10 个令牌,令牌桶容量为 20

      解释一下:

      • replenishRate: 每秒填充的令牌数量。
      • burstCapacity: 令牌桶的容量。
    • 自定义限流: 你可以自定义 KeyResolver 来实现更复杂的限流策略,例如根据用户 ID、IP 地址等进行限流。

  4. 熔断:保护服务,避免雪崩!

    熔断是指当某个服务出现故障时,停止对该服务的调用,防止故障扩散到其他服务,导致系统雪崩。Spring Cloud Gateway 可以集成 Hystrix 来实现熔断。

    • 集成 Hystrix:

      spring:
        cloud:
          gateway:
            routes:
              - id: hystrix-route
                uri: lb://user-service
                predicates:
                  - Path=/user/**
                filters:
                  - Hystrix=fallbackcmd

      需要配置 Hystrix 的 fallback 方法:

      @GetMapping("/fallback")
      public String fallback() {
          return "服务暂时不可用,请稍后再试!";
      }

      注意: Hystrix 已经停止维护,建议使用 Resilience4j 代替。Spring Cloud Gateway 提供了 Resilience4J 过滤器来集成 Resilience4j。

  5. 集成 Resilience4J

    Resilience4j是一个轻量级的,易于使用的容错库。

    • 添加依赖:

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
      </dependency>
    • 配置:

      spring:
      cloud:
      gateway:
        routes:
          - id: resilience4j-route
            uri: lb://user-service
            predicates:
              - Path=/user/**
            filters:
              - name: CircuitBreaker
                args:
                  name: userServiceCircuitBreaker
                  fallbackUri: forward:/defaultFallback
      circuitbreaker:
        configs:
          default:
            slidingWindowSize: 10
            failureRateThreshold: 50
            waitDurationInOpenState: 5s
            permittedNumberOfCallsInHalfOpenState: 3
            slowCallRateThreshold: 100
            slowCallDurationThreshold: 2s
        instances:
          userServiceCircuitBreaker:
            baseConfig: default
    • FallbackController

      @RestController
      public class FallbackController {
      
      @GetMapping("/defaultFallback")
      public String defaultFallback() {
          return "服务降级处理...";
      }
      }

五、监控:了解你的网关,才能更好地管理它!

监控是 API 网关的重要组成部分,可以帮助你了解网关的性能和运行状态,及时发现和解决问题。

  • Spring Boot Actuator: Spring Boot Actuator 提供了大量的监控指标,例如 CPU 使用率、内存使用率、请求数量、响应时间等。

    management:
      endpoints:
        web:
          exposure:
            include: "*" # 暴露所有端点

    访问 http://localhost:8080/actuator/metrics 可以查看所有监控指标。

  • Prometheus 和 Grafana: 可以使用 Prometheus 和 Grafana 来收集和展示监控数据,实现更强大的监控功能。

六、总结:API 网关,微服务架构的守护神!

API 网关是微服务架构中不可或缺的组件,它可以简化客户端的开发、解耦后端服务、提高系统的安全性、可用性和可维护性。Spring Cloud Gateway 是一个优秀的 API 网关,具有高性能、高并发、易扩展等特点,是你的不二之选。

希望通过今天的讲解,大家能够对 Spring Cloud Gateway 有更深入的了解,并能够运用到实际项目中。

最后,送大家一句话:

代码虐我千百遍,我待代码如初恋。🚀

下次再见! 😄

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注