限流器过滤器
RateLimiter 过滤器使用 Bucket4j 来判断当前请求是否被允许继续执行。如果不允许,则返回状态码 HTTP 429 - Too Many Requests
(默认情况下)。
在阅读本文档之前,请先查看 Bucket4j 概念。
Bucket4j 使用的算法是 令牌桶算法。
过滤器接受一个 keyResolver
参数以及其他 Bucket4j 配置参数。keyResolver
是一个 java.util.Function<ServerRequest, String>
类型的函数。这使得用户可以从请求中提取任何信息,并将其用作配置的 Bucket4j 分布式机制 中的键。常见的键值是从 ServerRequest
中获取的 Principal
。
默认情况下,如果 key 解析器没有找到 key,请求将被拒绝,并返回 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.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("https://example.org"))
.filter(rateLimit(c -> c.setCapacity(100)
.setPeriod(Duration.ofMinutes(1))
.setKeyResolver(request -> request.servletRequest().getUserPrincipal().getName())))
.build();
}
}
这配置了速率限制,每分钟的令牌桶容量为 100 个。key resolver
从 Servlet 请求中获取主体名称。