Guava RateLimiterのクイックガイド

1概要

この記事では、 httpsを見ていきます。] Guava__ライブラリからのクラス。

RateLimiter クラスは、何らかの処理が行われる割合を調整することを可能にする構成体です。 N個の許可を持つ RateLimiter を作成すると、プロセスは1秒あたり最大N個の許可を発行できます。

2 Mavenの依存関係

Guavaのライブラリを使用します。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>22.0</version>
</dependency>

最新版はhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22com.google.guava%22%20AND%20a%3A%22guava%22[here]にあります。

3 RateLimiter の作成と使用

doSomeLimitedOperation() の実行速度を毎秒2回に制限したいとしましょう。

create() ファクトリメソッドを使用して RateLimiter インスタンスを作成できます。

RateLimiter rateLimiter = RateLimiter.create(2);

次に、 RateLimiterから実行許可を取得するために、 acquire()__メソッドを呼び出す必要があります。

rateLimiter.acquire(1);

これを確認するために、スロットルされたメソッドを2回続けて呼び出します。

long startTime = ZonedDateTime.now().getSecond();
rateLimiter.acquire(1);
doSomeLimitedOperation();
rateLimiter.acquire(1);
doSomeLimitedOperation();
long elapsedTimeSeconds = ZonedDateTime.now().getSecond() - startTime;

テストを簡単にするために、 doSomeLimitedOperation() メソッドが直ちに完了したとしましょう。

このような場合、 acquire() メソッドの呼び出しは両方ともブロックしてはならず、経過時間は1秒以下にする必要があります。両方の許可をすぐに取得できるためです。

assertThat(elapsedTimeSeconds <= 1);

さらに、1回の__acquire()呼び出しですべての許可を取得できます。

@Test
public void givenLimitedResource__whenRequestOnce__thenShouldPermitWithoutBlocking() {
   //given
    RateLimiter rateLimiter = RateLimiter.create(100);

   //when
    long startTime = ZonedDateTime.now().getSecond();
    rateLimiter.acquire(100);
    doSomeLimitedOperation();
    long elapsedTimeSeconds = ZonedDateTime.now().getSecond() - startTime;

   //then
    assertThat(elapsedTimeSeconds <= 1);
}

たとえば、毎秒100バイトを送信する必要がある場合などに便利です。一度に1つの許可を取得するために、1バイトを100回送信できます。一方、1回の操作で100バイトの許可をすべて取得すると、100バイトすべてを一度に送信できます。

4ブロッキング方法で許可を取得する

それでは、もう少し複雑な例を考えてみましょう。

100の許可を持つ RateLimiter を作成します。それから、1000の許可を取得する必要があるアクションを実行します。 __RateLimiterの仕様によると、このようなアクションは1秒間に100ユニットのアクションしか実行できないため、完了までに少なくとも10秒かかります。

@Test
public void givenLimitedResource__whenUseRateLimiter__thenShouldLimitPermits() {
   //given
    RateLimiter rateLimiter = RateLimiter.create(100);

   //when
    long startTime = ZonedDateTime.now().getSecond();
    IntStream.range(0, 1000).forEach(i -> {
        rateLimiter.acquire();
        doSomeLimitedOperation();
    });
    long elapsedTimeSeconds = ZonedDateTime.now().getSecond() - startTime;

   //then
    assertThat(elapsedTimeSeconds >= 10);
}

ここでは、 acquire() メソッドをどのように使用しているかに注意してください。これはブロッキングメソッドであり、使用するときは注意が必要です。 acquire() メソッドは、呼び出されると、許可が得られるまで実行中のスレッドをブロックします。

  • 引数なしで acquire() を呼び出すことは、引数として1を指定して呼び出すことと同じです。** 1つの許可を取得しようとします。

5タイムアウト付きで許可を取得する

RateLimiter APIには、 timeout TimeUnit を引数として受け取る非常に便利な__acquire()メソッドもあります。

使用可能な許可がないときにこのメソッドを呼び出すと、指定された時間待機してからタイムアウトします( timeout. 内に使用可能な許可が十分にない場合)。

指定されたタイムアウト時間内に使用可能な許可がない場合は false. が返されます。 acquire()が成功した場合は return__ trueが返されます。

@Test
public void givenLimitedResource__whenTryAcquire__shouldNotBlockIndefinitely() {
   //given
    RateLimiter rateLimiter = RateLimiter.create(1);

   //when
    rateLimiter.acquire();
    boolean result = rateLimiter.tryAcquire(2, 10, TimeUnit.MILLISECONDS);

   //then
    assertThat(result).isFalse();
}

1つの許可を持つ RateLimiter を作成したので、2つの許可を取得しようとすると、常に tryAcquire() false. を返します。

6. 結論

このクイックチュートリアルでは、 Guava ライブラリの RateLimiter 構造体を見ました。

毎秒の許可数を制限するために RateLimtiter を使用する方法を学びました。ブロッキングAPIの使用方法を確認し、許可を取得するために明示的なタイムアウトも使用しました。

いつものように、これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/guava[GitHubプロジェクト]で見つけることができます - これはMavenプロジェクトなので簡単です。そのままインポートして実行します。