RateLimiter 过滤器
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,它是一个本地内存缓存,对测试很有用。
配置桶
默认情况下,桶是使用配置的 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 请求中获取主体名称。