Bucket4j 기본 개념 (Spring boot Rate Limiter

25gStroy·2022년 10월 5일
0

Springboot

목록 보기
37/41
post-thumbnail

bucket4j

Token Bucket알고리즘의 아이디어 위에 구현된 rate limit 라이브러리 입니다. io.github.bucket4j.Bucket 인터페이스로 표시 됩니다.
Token Bucket 알고리즘은 쉽게 말해서 패킷에 토큰을 심어놨다가 요청이 들어올때마다 하나씩 줄여서 0이 되면 요청을 거부하도록 하는 알고리즘인것 같습니다.

  • Token bucket 알고리즘 docs : https://en.wikipedia.org/wiki/Token_bucket
  • BucketConfiguration: 작업 중에 버킷에서 사용하는 변경할 수 없는 제한 규칙 모음을 지정합니다.
  • BucketState : 현제 사용가능한 토큰의 양과 변경가능한 상태를 버킷에 저장하는 위치

bucket은 다음과같이 빌더로 객체를 구성할 수 있다.

Bucket bucket = Bucket.builder()
   .addLimit(...)
   .build();

버킷 구성

BucketConfiguration은 작업중에 BucketBuilder는 백그라운드에서 자동으로 수행되기 때문에 BucketConfiguration를 직접 생성해선 안된다.

제한/ 대역폭

  • Capacity
    • 버킷에 있는 토큰 수를 지정합니다.
  • Refill
    • Refill은 버킷에서 사용한 후 토큰 재생성 속도를 제한
  • Initial tokens
    • Bucket4j는 각 대역폭에 대한 초기 토큰 양을 지정할 수 있도록 하여 토큰 버킷 알고리즘을 확장합니다. 기본적으로 토큰의 초기양은 용량과 같으며 withInitialTokens 매소드로 변경가능합니다.
Bandwidth bandwidth = Bandwidth.simple(42, Duration.ofMinutes(1))
                          .withInitialTokens(13);
  • ID
    • 식별자는 기본적으로 null 인 선택적 속성, 즉석 구성 교체를 사용하고 버킷에 버킷당 둘 이상의 대역폭이 있는 경우 대역폭에 대한 식별자를 할당하는것을 선홀할 수 있습니다. 그렇지 않으면 식별자를 사용하여 메모리를 보존치 않는것이 좋습니다.
    • 대역폭에 대한 식별자는 withId로 지정할 수 있다.
BucketConfiguration configuration = BucketConfiguration.builder()
        .addLimit(Bandwidth.simple(1000, Duration.ofMinutes(1)).withId("business-limit"))
        .addLimit(Bandwidth.simple(100, Duration.ofSeconds(1)).withId("burst-protection"))
        .build();

Refill

  • Greedy : bandwidth를 생성할때 사용되는 기본 리필 유형입니다.
// 아래 두 줄의 코드는 완전히 동일합니다.
Bandwidth.simple(100, Duration.ofMinutes(1))
Bandwidth.classic(100, Refill.greedy(100, Duration.ofMinutes(1)))
  • Interval : 리필은 간격방식으로 토큰을 재생성합니다. 전체 토큰을 재생성하기 전에 전체 기간이 경과할 때 까지 기다립니다.
// 분당 100개 토큰 생성
Refill.intervally(100, Duration.ofMinutes(1));
  • IntervallyAligend
    • 이 유형의 리필은 간격 방식으로 토큰을 다시 채우는 재생성 입니다. greedy와 반대되는 interval은 전체 토큰을 재생성하기 전에 전체 기간이 경과할 때 가지 대기합니다
      Interval외에도 첫번째 리필이 발생해야 하는 시간을 지정할 수 있습니다.
// 현제 시간이 16:20이라고 가정하고 첫 번째 리필은 17:00에 발생합니다.
// 첫 번째 리필은 다음 시간 초에 발생합니다.
Instant firstRefillTime = ZonedDateTime.now()
  .truncatedTo(ChronoUnit.HOURS)
  .plus(1, ChronoUnit.HOURS)
  .toInstant();

Bandwidth.classic(400, Refill.intervallyAligned(400, Duration.ofHours(1), firstRefillTime, true));

BucketState

BucketState는 버킷이 다음과 같이 변경 가능한 자체 상태를 저장하는 곳입니다.

  • 현재 사용 가능한 토큰의 양
  • 마지막 리필이 발생한 타임스탬프
  • io.github.bucket4j.BucketState 로 표시됩니다.

BucketBuilder

사용자가 직접 생성자를 통해 라이브러리의 객체를 구성하지 않도록 라이브러리 작성자가 명시적으로 결정한 결과물

그렇게 한이유는

  • 미래에 이전 버전과의 호환성을 깨뜨리지 않고 내부 구현을 변경할 수 있습니다.
  • 그것을 제공 Fluent Builder API 하는것은 현대적인 디자인 패턴이기 때문
Bucket bucket = Bucket.builder()
    .addLimit(Bandwidth.simple())
    .withNanosecondPrecision()
    .withSynchronizationStrategy(SynchronizationStrategy.LOCK_FREE)
    .build()

참고 : 8.x 버전부터 java8에서 java11로 마이그래이션함

출처 : https://bucket4j.com/8.1.0/toc.html#what-is-bucket4j

profile
애기 개발자

0개의 댓글