Panduan Cepat untuk Guava RateLimiter

1. Ikhtisar

Pada artikel ini, kita akan melihat kelas RateLimiter dari pustaka Guava .

Kelas RateLimiter adalah konstruksi yang memungkinkan kita untuk mengatur kecepatan di mana beberapa pemrosesan terjadi. Jika kita membuat RateLimiter dengan N izin - itu berarti proses dapat mengeluarkan paling banyak N izin per detik.

2. Ketergantungan Maven

Kami akan menggunakan perpustakaan Guava:

 com.google.guava guava 29.0-jre 

Versi terbaru dapat ditemukan di sini.

3. Membuat dan Menggunakan RateLimiter

Misalkan kita ingin membatasi laju eksekusi doSomeLimitedOperation () menjadi 2 kali per detik.

Kita dapat membuat instance RateLimiter menggunakan metode pabrik create () :

RateLimiter rateLimiter = RateLimiter.create(2);

Selanjutnya, untuk mendapatkan izin eksekusi dari RateLimiter, kita perlu memanggil metode acquiter () :

rateLimiter.acquire(1);

Untuk memeriksa apakah berhasil, kami akan melakukan 2 panggilan berikutnya ke metode throttled:

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

Untuk menyederhanakan pengujian kita, anggaplah metode doSomeLimitedOperation () selesai segera.

Dalam kasus seperti itu, kedua pemanggilan metode memperoleh () tidak boleh memblokir dan waktu yang telah berlalu harus kurang atau di bawah satu detik - karena kedua izin dapat diperoleh segera:

assertThat(elapsedTimeSeconds <= 1);

Selain itu, kami dapat memperoleh semua izin dalam satu panggilan memperoleh () :

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

Ini bisa berguna jika, misalnya, kita perlu mengirim 100 byte per detik. Kami dapat mengirim seratus kali satu byte untuk mendapatkan satu izin dalam satu waktu. Di sisi lain, kami dapat mengirim 100 byte sekaligus memperoleh semua 100 izin dalam satu operasi.

4. Memperoleh Izin dengan Cara Memblokir

Sekarang, mari kita pertimbangkan contoh yang sedikit lebih kompleks.

Kami akan membuat RateLimiter dengan 100 izin. Kemudian kami akan melakukan tindakan yang membutuhkan 1000 izin. Menurut spesifikasi RateLimiter, tindakan tersebut memerlukan setidaknya 10 detik untuk diselesaikan karena kami hanya dapat menjalankan 100 unit tindakan per detik:

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

Perhatikan, bagaimana kita menggunakan metode acquiring () di sini - ini adalah metode pemblokiran dan kita harus berhati-hati saat menggunakannya. Ketika metode memperoleh () dipanggil, ia memblokir thread yang menjalankan hingga izin tersedia.

Memanggil gain () tanpa argumen sama dengan memanggilnya dengan satu sebagai argumen - itu akan mencoba untuk mendapatkan satu izin.

5. Memperoleh Izin Dengan Batas Waktu

The RateLimiter API memiliki juga sangat berguna memperoleh () metode yang menerima batas waktu dan TIMEUNIT sebagai argumen.

Memanggil metode ini ketika tidak ada izin yang tersedia akan menyebabkannya menunggu waktu yang ditentukan dan kemudian waktu habis - jika tidak ada cukup izin yang tersedia dalam waktu tunggu.

Jika tidak ada izin yang tersedia dalam waktu tunggu yang diberikan, hasilnya palsu. Jika memperoleh () berhasil, itu mengembalikan nilai 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(); }

Kami membuat RateLimiter dengan satu izin jadi mencoba mendapatkan dua izin akan selalu menyebabkan tryAcquire () mengembalikan false.

6. Kesimpulan

Dalam tutorial singkat ini, kita telah melihat konstruksi RateLimiter dari library Guava .

Kami belajar bagaimana menggunakan RateLimtiter untuk membatasi jumlah izin per detik. Kami melihat cara menggunakan API pemblokirannya dan kami juga menggunakan batas waktu eksplisit untuk mendapatkan izin.

Seperti biasa, penerapan semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub - ini adalah proyek Maven, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.