RequestRateLimiter

RequestRateLimiter 网关过滤器工厂使用一个 RateLimiter 实现来确定当前请求是否被允许继续进行。如果不允许,将返回默认情况下的 HTTP 429 - Too Many Requests 状态。

此过滤器接受一个可选的 keyResolver 参数和特定于速率限制器的参数。

KeyResolver

keyResolver 是一个实现 KeyResolver 接口的 bean。在配置中,可以通过 SpEL(Spring Expression Language)引用此 bean。例如:#{@myKeyResolver} 是一个 SpEL 表达式,引用了一个名为 myKeyResolver 的 bean。

以下代码展示了 KeyResolver 接口:

public interface KeyResolver {

    /**
     * Resolve the key for the rate limiter.
     *
     * @param exchange the current exchange
     * @return the key for the rate limiter
     */
    Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver 的默认实现是 PrincipalNameKeyResolver,它从 ServerWebExchange 中获取 Principal 并调用 Principal.getName()。

默认情况下,如果 KeyResolver 找不到键,请求将被拒绝。

可以通过设置 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key(true 或 false)和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code 属性来调整此行为。

Redis RateLimiter

Redis 实现基于 Stripe 的工作,它要求使用 spring-boot-starter-data-redis-reactive。

Redis RateLimiter 使用的算法是令牌桶算法

  • redis-rate-limiter.replenishRate 属性定义了每秒允许多少请求(不包括任何被丢弃的请求)。这是令牌桶填充的速率

  • redis-rate-limiter.burstCapacity 属性是用户在一秒内允许的最大请求数(不包括任何被丢弃的请求)。这是令牌桶可以容纳的令牌数量

    将此值设置为零会阻止所有请求。

  • redis-rate-limiter.requestedTokens 属性是每个请求消耗的令牌数。这是每个请求从令牌桶中取走的令牌数,默认为 1。

  • 通过将 replenishRate 和 burstCapacity 设置为同样的值可以实现稳定的速率。

  • 通过将 burstCapacity 设置得高于 replenishRate,可以允许临时的请求突发。在这种情况下,速率限制器需要在两个连续的突发之间留出一些时间(根据 replenishRate),因为连续的两个突发会导致请求被丢弃(HTTP 429 - Too Many Requests)。

将速率限制设置为低于 1 请求/秒的方式是将 replenishRate 设置为所需请求数,将 requestedTokens 设置为以秒为单位的时间跨度,将 burstCapacity 设置为 replenishRate 和 requestedTokens 的乘积。

例如,设置 replenishRate=1,requestedTokens=60,和 burstCapacity=60 将得到一个 1 请求/分钟的限制。

以下配置示例演示了如何配置 redis-rate-limiter:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20
            redis-rate-limiter.requestedTokens: 1

上述配置定义了每个用户的请求速率限制为 10。允许突发量为 20,但在下一秒中只有 10 个请求可用。

以下示例演示了如何在 Java 中配置一个 KeyResolver:

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(
        exchange.getRequest().getQueryParams().getFirst("user")
    );
}

KeyResolver 是一个简单的实现,它获取用户请求参数。

还可以将速率限制器定义为实现 RateLimiter 接口的 bean。在配置中,可以使用 SpEL 引用该 bean。#{@myRateLimiter} 是一个 SpEL 表达式,引用了名为 myRateLimiter 的 bean。以下示例定义了一个速率限制器,它使用了前面示例中定义的 KeyResolver:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

Last updated