RequestRateLimiter
GatewayFilter
工厂
RequestRateLimiter
GatewayFilter
Factory
RequestRateLimiter
GatewayFilter
工厂使用 RateLimiter
实现来确定当前请求是否允许继续。如果不允许,默认情况下会返回 HTTP 429 - 请求过多
的状态码。
该过滤器接受一个可选的 keyResolver
参数以及特定于速率限制器的参数(在本节后面 部分中描述)。
keyResolver
是一个实现了 KeyResolver
接口的 bean。在配置中,使用 SpEL 通过名称引用该 bean。#{@myKeyResolver}
是一个 SpEL 表达式,它引用了一个名为 myKeyResolver
的 bean。以下清单展示了 KeyResolver
接口:
public interface KeyResolver {
Mono<String> resolve(ServerWebExchange exchange);
}
KeyResolver
接口允许可插拔的策略派生用于限制请求的密钥。在未来的里程碑版本中,将会提供一些 KeyResolver
实现。
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
属性来调整此行为。
RequestRateLimiter
无法使用“快捷”表示法进行配置。以下示例是无效的:
# 无效的快捷配置
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}
以下是一个有效的 yaml 参考配置:
spring:
cloud:
gateway:
routes:
- id: limit
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userkeyresolver}"
Redis RateLimiter
Redis 的实现基于 Stripe 的工作成果。它需要使用 spring-boot-starter-data-redis-reactive
Spring Boot starter。
所使用的算法是 令牌桶算法。
redis-rate-limiter.replenishRate
属性定义了每秒允许的请求数量(不丢弃任何请求)。这是令牌桶填充的速率。
redis-rate-limiter.burstCapacity
属性表示用户在一秒钟内允许的最大请求数(不丢弃任何请求)。这是令牌桶可以持有的令牌数量。将此值设置为零将阻止所有请求。
redis-rate-limiter.requestedTokens
属性表示每次请求消耗的令牌数量。这是从令牌桶中为每个请求提取的令牌数量,默认值为 1
。
通过将 replenishRate
和 burstCapacity
设置为相同的值,可以实现稳定的速率。通过将 burstCapacity
设置为高于 replenishRate
,可以允许临时突发。在这种情况下,速率限制器需要在突发之间留出一些时间(根据 replenishRate
),因为连续两次突发会导致请求被丢弃(HTTP 429 - 请求过多
)。以下列表配置了一个 redis-rate-limiter
:
低于 1 请求/秒
的速率限制通过将 replenishRate
设置为所需的请求数,requestedTokens
设置为时间跨度(以秒为单位),并将 burstCapacity
设置为 replenishRate
和 requestedTokens
的乘积来实现。例如,设置 replenishRate=1
,requestedTokens=60
,以及 burstCapacity=60
将导致限制为 1 请求/分钟
。
.application.yml
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
以下示例在 Java 中配置了一个 KeyResolver
:
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}
这定义了一个每个用户 10 次的请求速率限制。允许突发 20 次请求,但在下一秒,只有 10 次请求可用。KeyResolver
是一个简单的解析器,用于获取 user
请求参数。注意:不建议在生产环境中使用。
你也可以定义一个实现了 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}"