LoginSignup
2
0

More than 3 years have passed since last update.

Resilience4j の RateLimiter を用いた Rate-Limitting

Posted at

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 のミドルウェアを導入した方が望ましいと思います。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0