Hurtig vejledning til Guava RateLimiter

1. Oversigt

I denne artikel ser vi på RateLimiter klasse fra Guava bibliotek.

Det RateLimiter klasse er en konstruktion, der giver os mulighed for at regulere den hastighed, hvormed en eller anden behandling sker. Hvis vi opretter en RateLimiter med N-tilladelser - det betyder, at processen højst kan udstede N-tilladelser pr. sekund.

2. Maven-afhængighed

Vi bruger Guavas bibliotek:

 com.google.guava guava 29.0-jre 

Den seneste version kan findes her.

3. Oprettelse og brug RateLimiter

Lad os sige, at vi vil begrænse hastigheden for udførelsen af doSomeLimitedOperation () til 2 gange i sekundet.

Vi kan oprette en RateLimiter eksempel ved hjælp af dens skab() fabriksmetode:

RateLimiter rateLimiter = RateLimiter.create (2);

Dernæst for at få en eksekveringstilladelse fra RateLimiter, vi er nødt til at kalde erhverve() metode:

rateLimiter.acquire (1);

For at kontrollere, at det fungerer, foretager vi 2 efterfølgende opkald til gasbegrænsningsmetoden:

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

Lad os antage det for at forenkle vores test doSomeLimitedOperation () metoden fuldføres straks.

I så fald er begge påkald af erhverve() metoden bør ikke blokere, og den forløbne tid skal være mindre eller under et sekund - fordi begge tilladelser kan erhverves med det samme:

assertThat (elapsedTimeSeconds <= 1);

Derudover kan vi erhverve alle tilladelser i én erhverve() opkald:

@Test offentlig ugyldighed givenLimitedResource_whenRequestOnce_thenShouldPermitWithoutBlocking () {// given RateLimiter rateLimiter = RateLimiter.create (100); // når lang starttid = ZonedDateTime.now (). getSecond (); rateLimiter.acquire (100); doSomeLimitedOperation (); long elapsedTimeSeconds = ZonedDateTime.now (). getSecond () - startTime; // derefter assertThat (elapsedTimeSeconds <= 1); }

Dette kan være nyttigt, hvis vi f.eks. Har brug for at sende 100 byte pr. Sekund. Vi kan sende hundrede gange en byte, der får én tilladelse ad gangen. På den anden side kan vi sende alle 100 byte på én gang og erhverve alle 100 tilladelser i en operation.

4. Erhvervelse af tilladelser på en blokerende måde

Lad os nu overveje et lidt mere komplekst eksempel.

Vi opretter en RateLimiter med 100 tilladelser. Så udfører vi en handling, der skal erhverve 1000 tilladelser. I henhold til specifikationen for RateLimiter, en sådan handling har brug for mindst 10 sekunder for at fuldføre, fordi vi kun er i stand til at udføre 100 handlinger pr. sekund:

@Test offentlig ugyldighed givenLimitedResource_whenUseRateLimiter_thenShouldLimitPermits () {// given RateLimiter rateLimiter = RateLimiter.create (100); // når lang starttid = ZonedDateTime.now (). getSecond (); IntStream.range (0, 1000) .forEach (i -> {rateLimiter.acquire (); doSomeLimitedOperation ();}); long elapsedTimeSeconds = ZonedDateTime.now (). getSecond () - startTime; // derefter assertThat (elapsedTimeSeconds> = 10); }

Bemærk, hvordan vi bruger erhverve() metode her - dette er en blokeringsmetode, og vi skal være forsigtige, når vi bruger den. Når erhverve() metode kaldes, blokerer den eksekveringstråden, indtil en tilladelse er tilgængelig.

Ringer til erhverve() uden argument er det samme som at kalde det med et som argument - det vil forsøge at erhverve en tilladelse.

5. Erhvervelse af tilladelser med en timeout

Det RateLimiter API har også en meget nyttig erhverve() metode, der accepterer en tiden er gået og TimeUnit som argumenter.

At kalde denne metode, når der ikke er nogen tilgængelige tilladelser, får den til at vente på et bestemt tidspunkt og derefter timeout - hvis der ikke er nok tilgængelige tilladelser inden for tiden er gået.

Når der ikke er nogen tilgængelige tilladelser inden for den givne timeout, vender den tilbage falsk. Hvis en erhverve() lykkes, det vender tilbage rigtigt:

@Test offentlig ugyldighed givenLimitedResource_whenTryAcquire_shouldNotBlockIndefinitely () {// given RateLimiter rateLimiter = RateLimiter.create (1); // når rateLimiter.acquire (); boolesk resultat = rateLimiter.tryAcquire (2, 10, TimeUnit.MILLISECONDS); // derefter assertThat (resultat) .isFalse (); }

Vi oprettede en RateLimiter med en tilladelse, så forsøg på at erhverve to tilladelser vil altid medføre tryAcquire () at vende tilbage falsk.

6. Konklusion

I denne hurtige vejledning kiggede vi på RateLimiter konstruere fra Guava bibliotek.

Vi lærte at bruge RateLimtiter for at begrænse antallet af tilladelser pr. sekund. Vi så, hvordan vi bruger dens blokerende API, og vi brugte også en eksplicit timeout til at erhverve tilladelsen.

Som altid kan implementeringen af ​​alle disse eksempler og kodestykker findes i GitHub-projektet - dette er et Maven-projekt, så det skal være let at importere og køre som det er.