Spring Cloud Gateway的API速率限制 - spring.io


架构上当务之急之一是保护API和服务端点免受有害影响,例如拒绝服务,级联故障。或过度使用资源。速率限制是一种控制使用API​​或服务的速率的技术。在分布式系统中,没有比集中配置和管理使用者可以与API交互的速率更好的选择了。只有在规定速率内的那些请求才可以进入API。否则将引发HTTP“许多请求”错误。
Spring Cloud Gateway(SCG)是一个简单轻巧的组件,但是它是管理限制API使用率的有效方法。在此博客中,我将说明使用配置方法可以多么简单地完成该任务。如下图所示,该演示由前端和后端服务以及介于两者之间的Spring Cloud Gateway服务组成。

无需任何代码即可将SCG包括在体系结构中。您需要org.springframework.cloud:spring-cloud-starter-gateway在原始Spring Boot应用程序中包含Spring Boot Cloud依赖项,并且已设置为具有适当的配置设置。
SCG从前端服务收到的请求可以基于配置的路由定义路由到后端服务。路由定义配置向网关指定如何将请求路由到后端端点。路由配置通常基于可从HTTP请求中提取的信息(例如路径和标头)来定义条件。
例如,下面的代码段列出了YAML节,以配置将请求路由到后端服务的条件。它显示当路径中用“ / backend”命中网关时,请求应以后端服务为目标。在配置中,为路由提供了一个标识符和后端服务URI。

spring:
  cloud:
    gateway:
      routes:
        - id: route1
          uri: http://localhost:8081
          predicates:
            - Path=/backend

RequestRateLimiter是SCG提供的众多网关过滤器之一。该实现确定请求是允许继续进行还是已超过其限制。该实现使您(可选)插入密钥来管理限制对不同服务的请求数。虽然可以自定义实现密钥的解析方式,但网关随附使用用户的主体名称的密钥。需要安全的网关来解析用户的主体名称,但是您可以选择实现KeyResolver接口,以替代解析ServerWebExchange的其他密钥。您可以使用SPEL #{@ customKeyResolver}指向配置中的自定义KeyResolver bean(例如,名为customKeyResolver)。表达。以下清单显示了KeyResolver接口:
public interface KeyResolver {
    Mono<String> resolve(ServerWebExchange exchange);
}

如果没有密钥解决,网关将拒绝请求。要让网关接受缺少的已解析密钥,可以设置以下属性:
spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key=false

您还可以通过设置以下属性,指定网关在找不到密钥时应报告的状态代码:
spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code=

 
案例应用
考虑一个架构:其中网关通过使用Redis控制限制API的使用。提供的Redis实现使用令牌桶算法。要使用它,您需要spring-boot-starter-data-redis在网关应用程序中包括Spring Boot启动程序依赖项。基本上,令牌桶算法使用余额令牌作为一种手段来维持累积的使用预算。该算法假定令牌将以一定速率添加到存储桶中,而从这些令牌中调用API会消耗这些令牌。一个API调用可以执行许多操作来组成响应,以便满足请求(考虑基于GraphQL的API)。在这种情况下,该算法有助于识别一个调用可能会花费一个API多个令牌。


提供的Redis实现使您可以定义请求速率,用户可以在特定时间段内以该速率进行呼叫。这也使得有可能适应零散的需求,同时受到定义的消耗率的限制。
可以通过设置redis-rate-limiter.replenishRate=500属性来定义每秒500个请求的补充速率,并且可以通过设置属性edis-rate-limiter.burstCapacity=1000来定义每秒1000个请求的突发容量,这样做会将消耗限制为每秒500个请求。如果请求数量突然增加,则仅允许1,000个请求,但是,由于1,000个请求的配额为2秒,因此网关不会在下一秒内路由请求。
该配置还允许您通过设置propertyredis-rate-limiter.requestedTokens属性来定义一个请求将花费多少个令牌。通常,它设置为1。
要使用具有请求限制功能的网关,需要使用RequestRateLimiter网关过滤器对其进行配置。该配置可以指定参数来定义补充率,突发容量和请求花费的令牌数量。下面的示例说明了如何使用这些参数配置网关:

spring:
  cloud:
    gateway:
      routes:
        - id: route1
          uri: http://localhost:8081
          predicates:
            - Path=/backend
          filters:
          - name: RequestRateLimiter
            args:
              redis-rate-limiter.replenishRate: 500
              redis-rate-limiter.burstCapacity: 1000
              redis-rate-limiter.requestedTokens: 1


Spring Cloud Gateway可以灵活地定义您自己的自定义速率限制器实现。它提供了RateLimiter接口来实现和定义bean。可以使用SPEL表达式来配​​置速率限制器bean,就像在自定义密钥解析器中一样。例如,您可以定义一个名为customRateLimiter的自定义速率限制器bean和一个名为customKeyResolver的自定义密钥解析器,并配置如下路由:

@Bean
public KeyResolver customKeyResolver {
    return exchange -> ....  // returns a Mono of String
}

spring:
  cloud:
    gateway:
      routes:
        - id: route1
          uri: http://localhost:8081
          predicates:
            - Path=/backend
          filters:
          - name: RequestRateLimiter
            args:
              rate-limiter: "#{customRateLimiter}"
              key-resolver: "#{customKeyResolver}"

GitHub上有一个说明性示例
相关:
阿里巴巴哨兵Sentinel简介 | Baeldung