Guide rapide du limiteur de taux de goyave

Guide rapide du limiteur de taux de goyave

1. Vue d'ensemble

Dans cet article, nous allons examiner la classeRateLimiter de la bibliothèqueGuava.

La classeRateLimiter est une construction qui nous permet de réguler la vitesse à laquelle certains traitements se produisent. Si nous créons unRateLimiter avec N permis - cela signifie que le processus peut émettre au plus N permis par seconde.

2. Dépendance Maven

Nous utiliserons la bibliothèque de Guava:


    com.google.guava
    guava
    22.0

La dernière version peut être trouvéehere.

3. Création et utilisation deRateLimiter

Disons que nous voulonslimit the rate of execution of the doSomeLimitedOperation() to 2 times per second.

Nous pouvons créer une instanceRateLimiter en utilisant sa méthode d'usinecreate():

RateLimiter rateLimiter = RateLimiter.create(2);

Ensuite, pour obtenir un permis d'exécution desRateLimiter,, nous devons appeler la méthodeacquire():

rateLimiter.acquire(1);

Afin de vérifier que cela fonctionne, nous allons effectuer deux appels ultérieurs à la méthode limitée:

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

Pour simplifier nos tests, supposons que la méthodedoSomeLimitedOperation() se termine immédiatement.

Dans ce cas, les deux appels de la méthodeacquire() ne doivent pas bloquer et le temps écoulé doit être inférieur ou inférieur à une seconde - car les deux autorisations peuvent être acquises immédiatement:

assertThat(elapsedTimeSeconds <= 1);

De plus, nous pouvons acquérir tous les permis en un seul appelacquire():

@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);
}

Cela peut être utile si, par exemple, nous devons envoyer 100 octets par seconde. Nous pouvons envoyer cent fois un octet en acquérant un permis à la fois. D'autre part, nous pouvons envoyer tous les 100 octets simultanément en acquérant tous les 100 permis en une seule opération.

4. Acquérir des permis de manière bloquante

Prenons maintenant un exemple légèrement plus complexe.

Nous allons créer unRateLimiter avec 100 permis. Ensuite, nous exécuterons une action qui nécessite l’acquisition de 1 000 permis. Selon la spécification desRateLimiter,, une telle action nécessitera au moins 10 secondes, car nous ne pouvons exécuter que 100 unités d'action par seconde:

@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);
}

Remarquez comment nous utilisons la méthodeacquire() ici - c'est une méthode bloquante et nous devons être prudents lorsque vous l'utilisez. Lorsque la méthodeacquire() est appelée, elle bloque le thread en cours d'exécution jusqu'à ce qu'un permis soit disponible.

Calling the acquire() without an argument is the same as calling it with a one as an argument - il essaiera d'acquérir un permis.

5. Obtention de permis avec un délai d'expiration

L'APIRateLimiter a également une méthodeacquire() très utile queaccepts a timeout and TimeUnit as arguments.

L'appel de cette méthode quand il n'y a pas de permis disponibles la fera attendre pendant le temps spécifié, puis expirera - s'il n'y a pas assez de permis disponibles dans lestimeout.

Lorsqu'aucun permis n'est disponible dans le délai imparti, il renvoiefalse. Si unacquire() réussit, ilreturnsest vrai:

@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();
}

Nous avons créé unRateLimiter avec un permis donc essayer d'acquérir deux permis fera toujours quetryAcquire() renvoiefalse.

6. Conclusion

Dans ce rapide tutoriel, nous avons examiné la constructionRateLimiter de la bibliothèqueGuava.

Nous avons appris à utiliser lesRateLimtiter pour limiter le nombre de permis par seconde. Nous avons vu comment utiliser son API de blocage et nous avons également utilisé un délai d’attente explicite pour acquérir le permis.

Comme toujours, l'implémentation de tous ces exemples et extraits de code se trouve dans leGitHub project - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.