RateLimiter Filter

RateLimiter Filter 使用 Bucket4j 确定是允许当前请求继续进行。如果不是,则返回状态 HTTP 429 - Too Many Requests(默认)。

The RateLimiter Filter use Bucket4j to determine if the current request is allowed to proceed. If it is not, a status of HTTP 429 - Too Many Requests (by default) is returned.

在阅读本文档之前,请先查看 Bucket4j Concepts

Please review Bucket4j Concepts prior to reading this documentation.

Bucket4j 使用的算法是 Token Bucket Algorithm

The algorithm used by Bucket4j is the Token Bucket Algorithm.

该过滤器采用 keyResolver 参数和其他 Bucket4j 配置参数。键解析器是 java.util.Function<ServerRequest, String>。这使用户能够从请求中提取任何信息,以用作在已配置的 Bucket4j distribution 机制中作为键。一个常见的键将是从 ServerRequest 检索到的 Principal

The filter takes a keyResolver parameter and other Bucket4j configuration parameters. The key resolver is a java.util.Function<ServerRequest, String>. This allows the user to extract any information out of the request to use as a key in the configured Bucket4j distribution mechanism. A common key would be the Principal retrieved from the ServerRequest.

默认情况下,如果关键解析器找不到键,那么将会以 FORBIDDEN 状态拒绝请求。

By default, if the key resolver does not find a key, requests are denied with the FORBIDDEN status.

当前,配置键解析器的唯一方法是通过 Java DSL 而不是通过外部属性。

Currently, the only way to configure key resolvers is through the Java DSL and not through external properties.

Bucket4j Distributed Configuration

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

A bean of type io.github.bucket4j.distributed.proxy.AsyncProxyManager. To do this, use the ProxyManager.asAsync() method.

RateLimiterConfiguration.java
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,对于测试非常有用。

The above configures an AsyncProxyManager using Caffeine, a local in-memory cache, useful for testing.

Configuring Buckets

默认情况下,Bucket 会使用已配置的 “capacity” 和 “period” 进行配置。容量是指 Bucket 中有多少个令牌。period 是一个 java.util.Duration,它定义了 Bucket 中可用的令牌重新生成的时长。

By default, the Bucket is configured using a configured capacity and period. Capacity is how many tokens the bucket has. The period is a java.util.Duration that defines how long for the tokens available in the bucket to be regenerated.

其他配置项是请求被拒绝时返回的 statusCode。默认情况下它为 429,即 TO_MANY_REQUESTS。tokens 项定义每个请求使用了多少令牌,默认值为 1。headerName 项是包含剩余令牌数的标头的名称,默认为 X-RateLimit-Remainingtimeout 选项为分布式 Bucket 返回答案定义一个 Duration,默认情况下不会设置。

Other configuration items are the statusCode returned when the request is denied. By default it is 429, TO_MANY_REQUESTS. The tokens item defines how many tokens are used for each request and defaults to 1. The headerName item is the name of the header that contains the number of remaining tokens, this defaults to X-RateLimit-Remaining. The timeout option defines a Duration for the distributed bucket to return an answer and is not set by default.

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

The following is an example of configuring a route with rate limiting:

RouteConfiguration.java
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 个令牌的 Bucket 容量来配置限流。密钥解析器从 Servlet 请求中获取主体名称。

This configures the rate limiting with a bucket capacity of 100 tokens per minute. The key resolver gets the principle name from the Servlet request.