resilience4j は主に Java 向けの Circuit Breaker 実装として著名なものになる。Rate-Limitting 関連の機能も存在している。
以下では以下のサンプルプログラムをベースに検証を行っている。
Configuration
build.gradle
Spring Boot と連携をする場合は 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}") // <-
application.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
limitForPeriod: 3
, limitRefreshPeriod: 2s
だと、2秒以内に3回を超えるアクセスがあると Rate-Limitting が行われる。
Java
Rate-Limitting を設定する処理に、@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";
}
Running
今回の設定では、2秒間に3回を超えるアクセスをすると500エラーが返却される。
通常時(200)
< 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
Rate-Limit 時(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"
}
内部的には RequestNotPermitted
という RuntimeException が発生するため、Controller 層などで適切なエラーハンドリングと HTTP StatusCode の返却処理をする必要がある。
Monitoring
/actuator/ratelimiters
で Rate-Limit 関連の設定内容を取得することができる。
{
"rateLimiters" : [ "backendA", "backendB" ]
}
Conclusion
resilience4j ならびに resilience4j-spring-boot2 を用いると、かなり簡単に既存の Spring Boot アプリケーションに Rate-Limiting の機能を追加することができる。
bucket4j との差は、URL の Path やユーザー単位の Rate-Limitting 処理は標準では対応していないこと、になります。
本格的に Rate-Limiting の処理をシステム全体に適用する場合は、Ambassador Pattern や Side-Car Pattern を用いて API Gateway のミドルウェアを導入した方が望ましいと思います。