Home > Net >  Java Spring rate limiter block specific duration when ratio reached
Java Spring rate limiter block specific duration when ratio reached

Time:10-15

Currently I have a requirement: Apply rate limiter for an API. If this API get called over 100 times per 5 sec then the API will be blocked for 10 mins. I don't know if there is any java lib can fullfill this requirement. If the requirement is "Allow 100 calls per 5 sec" or "Allow 100 calls per 10 min" then I can either user Bucket4j:

Bandwidth b = Bandwidth.classic(100, Refill.intervally(100, Duration.ofSeconds(5)));
//Bandwidth b = Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(10)));
Bucket bk = Bucket.builder().addLimit(b).build();

//then
if(bk.tryConsume(1)) {
    //stuff
} else {
    throw
}

or Resilence4j:

RateLimiterConfig config = RateLimiterConfig.custom()
            .limitRefreshPeriod(Duration.ofSeconds(5))
            .limitForPeriod(100)
            .timeoutDuration(Duration.ofSeconds(1))
            .build();
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config);
RateLimiter rateLimiterWithCustomConfig = rateLimiterRegistry
            .rateLimiter("name2", config);
CheckedRunnable restrictedCall = RateLimiter
            .decorateCheckedRunnable(rateLimiterWithCustomConfig, this::doStuff);

//then
Try.run(restrictedCall).onFailure(throwable -> throw new RuntimeException());

But the requirement is "Allow 100 calls per 5 sec, if more, block 10 min". Is there any lib can work? Please suggest me a solution for this case. Thank you

CodePudding user response:

There is currently this feature for Bucket4j to block a bucket for a certain period of time. (I can say the same in Resilence4j but I'm not so sure!)

So you should to maintain blacklisting manually. (This will require more complex code improvements depending on the use case!)

However, I think using 2 different limits as below is better in terms of code cost. (You can keep the 10-minute period somewhat flexible and maintain the 5-second condition.)

Bandwidth bandwidth1 = Bandwidth.classic(
        1200, Refill.intervally(
                1200, Duration.ofMinutes(10)));
Bandwidth bandwidth2 = Bandwidth.classic(
        100, Refill.intervally(
                100, Duration.ofSeconds(5)));

Bucket bucket = Bucket.builder()
        .addLimit(bandwidth1)
        .addLimit(bandwidth2)
        .build();
  • Related