跳到主要内容
版本:5.0.1

RateLimiter 过滤器

DeepSeek V3 中英对照 RateLimiter Filter

RateLimiter 过滤器使用 Bucket4j 来判断当前请求是否允许继续执行。如果不允许,则返回 HTTP 429 - Too Many Requests 状态码(默认情况下)。

在阅读本文档之前,请先查阅 Bucket4j 概念。

Bucket4j 所使用的算法是 令牌桶算法。

过滤器接收一个 keyResolver 参数以及其他 Bucket4j 配置参数。该键解析器是一个 java.util.Function<ServerRequest, String>。这允许用户从请求中提取任何信息,用作已配置的 Bucket4j 分布式特性 机制中的键。一个常见的键是从 ServerRequest 中获取的 Principal。

默认情况下,如果密钥解析器未找到密钥,请求将被拒绝并返回 FORBIDDEN 状态。

备注

目前,配置密钥解析器的唯一方式是通过 Java DSL,而不是通过外部属性。

Bucket4j 分布式配置​

一个类型为 io.github.bucket4j.distributed.proxy.AsyncProxyManager 的 bean。为此,请使用 ProxyManager.asAsync() 方法。

import com.github.benmanes.caffeine.cache.Caffeine;
import io.github.bucket4j.caffeine.CaffeineProxyManager;

@Configuration
class RateLimiterConfiguration {

@Bean
public AsyncProxyManager<String> caffeineProxyManager() {
Caffeine<String, RemoteBucketState> builder = (Caffeine) Caffeine.newBuilder().maximumSize(100);
return new CaffeineProxyManager<>(builder, Duration.ofMinutes(1)).asAsync();
}
}

上述配置使用 Caffeine 实现了一个 AsyncProxyManager,这是一个本地内存缓存,适用于测试场景。

配置存储桶​

默认情况下,Bucket 通过配置的 capacity 和 period 进行配置。Capacity 是桶拥有的令牌数量。Period 是一个 java.util.Duration,它定义了桶中可用令牌的再生时间。

其他配置项包括请求被拒绝时返回的statusCode,默认值为 429,即 TO_MANY_REQUESTS。tokens 项定义了每个请求消耗的令牌数量,默认值为 1。headerName 项是包含剩余令牌数量的响应头名称,默认值为 X-RateLimit-Remaining。timeout 选项定义了分布式令牌桶返回响应的 Duration,默认情况下未设置。

以下是一个配置路由限流的示例:

import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.Bucket4jFilterFunctions.rateLimit;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

@Bean
public RouterFunction<ServerResponse> gatewayRouterFunctionsRateLimited() {
return route("rate_limited_route")
.GET("/api/**", http())
.before(uri("https://example.org"))
.filter(rateLimit(c -> c.setCapacity(100)
.setPeriod(Duration.ofMinutes(1))
.setKeyResolver(request -> request.servletRequest().getUserPrincipal().getName())))
.build();
}
}

这将配置速率限制,桶容量为每分钟100个令牌。密钥解析器从Servlet请求中获取主体名称。