使用 Resilience4j 的 RateLimiter 进行速率限制
resilience4j是一个主要针对Java的著名断路器实现。它还具备与速率限制相关的功能。
我们在以下基础上进行验证的是下方的示例程序。
配置
通过使用 build.gradle 文件构建
如果要将Spring Boot与Resilience4j集成,则使用io.github.resilience4j:resilience4j-spring-boot2。
dependencies {
compile('org.springframework.boot:spring-boot-starter-webflux')
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.springframework.boot:spring-boot-starter-aop')
compile("io.github.resilience4j:resilience4j-spring-boot2:${resilience4jVersion}") // <-
应用配置文件.yml
resilience4j.ratelimiter:
configs:
default:
registerHealthIndicator: false
limitForPeriod: 3
limitRefreshPeriod: 2s
timeoutDuration: 0
eventConsumerBufferSize: 100
instances:
backendA:
baseConfig: default
backendB:
limitForPeriod: 6
limitRefreshPeriod: 500ms
timeoutDuration: 3s
当限制周期为2秒且在此期间内访问次数超过3次时,将进行速率限制。
Java:Java是一种面向对象的编程语言,具有简单、可移植、可扩展和高性能等特点。
在设置速率限制的处理中,设置@RateLimiter注解。
@Override
@RateLimiter(name = BACKEND_A) // <--
@CircuitBreaker(name = BACKEND_A)
@Bulkhead(name = BACKEND_A)
@Retry(name = BACKEND_A)
public String success() {
return "Hello World from backend A";
}
奔跑
根据本次设定,如果在2秒内进行超过3次的访问,将返回500错误。
两百的普通时间
< HTTP/1.1 200 OK
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 26
<
* Connection #0 to host localhost left intact
Hello World from backend A
速率限制时(500)
< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Content-Length: 235
<
{
"timestamp" : "2020-05-05T09:23:13.530+0000",
"path" : "/backendA/success",
"status" : 500,
"error" : "Internal Server Error",
"message" : "RateLimiter 'backendA' does not permit further calls",
"requestId" : "b372ed49"
}
内部有 RuntimeException 引发 RequestNotPermitted,因此在控制器层等需要适当处理错误和返回适当的 HTTP 状态码的处理。
监控
可以使用/actuator/ratelimiters来获取与速率限制相关的配置信息。
{
"rateLimiters" : [ "backendA", "backendB" ]
}
结论
使用resilience4j和resilience4j-spring-boot2,在现有的Spring Boot应用程序中轻松添加速率限制功能。
与bucket4j的不同之处在于它不支持URL路径或基于用户的速率限制处理。
如果要在系统中全面应用Rate-Limiting处理的话,我认为最好是使用Ambassador Pattern或Side-Car Pattern来引入API Gateway的中间件。