Rate Limiting в Java: библиотеки и инструменты для контроля запросов (Bucket4j, Resilience4j)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Ограничение частоты запросов (Rate Limiting) в Java: обзор библиотек и инструментов

Rate limiting (ограничение частоты запросов) — критически важный механизм для защиты веб-сервисов, API и микросервисов от перегрузок, DDoS-атак и случайного злоупотребления. В Java существует несколько зрелых библиотек, реализующих различные алгоритмы: от простого счетчика до сложных распределенных систем. В этой статье мы рассмотрим три основных подхода: Guava RateLimiter, Bucket4j и Resilience4j, а также обсудим их применение.

1. Guava RateLimiter (простой и легковесный)

Библиотека Google Guava предоставляет класс RateLimiter, реализующий алгоритм Token Bucket (корзина токенов) в однопоточном режиме. Он идеально подходит для локального использования в одном JVM-процессе.

Принцип работы: Корзина наполняется токенами с определенной скоростью. Каждый запрос забирает один или несколько токенов. Если токенов недостаточно, поток блокируется или запрос отклоняется.

Пример использования Guava RateLimiter:

import com.google.common.util.concurrent.RateLimiter;

public class GuavaRateLimiterExample {
    public static void main(String[] args) {
        // Создаем RateLimiter на 10 запросов в секунду
        RateLimiter rateLimiter = RateLimiter.create(10.0);

        // Имитация входящих запросов
        for (int i = 0; i < 20; i++) {
            // tryAcquire() возвращает true, если токен получен
            if (rateLimiter.tryAcquire()) {
                System.out.println("Запрос " + i + " выполнен");
            } else {
                System.out.println("Запрос " + i + " отклонен (лимит превышен)");
            }
        }
    }
}

Плюсы: Минимальная зависимость, простота, низкое потребление памяти.
Минусы: Не подходит для распределенных систем (не синхронизируется между инстансами).

2. Bucket4j (продвинутый Token Bucket с поддержкой Redis)

Bucket4j — это библиотека, реализующая алгоритм Token Bucket с расширенными возможностями: поддержка нескольких провайдеров для хранения состояния (in-memory, Redis, Hazelcast, Infinispan), что позволяет использовать её в распределенных сценариях.

Ключевые особенности:

  • Поддержка greedy и interval-based режимов.
  • Возможность задавать лимиты на разные временные окна (например, 100 запросов в минуту + 10 запросов в секунду).
  • Интеграция с Jakarta EE / Spring Boot через готовые фильтры и аннотации.

Пример с in-memory хранилищем:

import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Refill;

import java.time.Duration;

public class Bucket4jExample {
    public static void main(String[] args) {
        // Лимит: 5 запросов в 10 секунд
        Bandwidth limit = Bandwidth.classic(5, Refill.intervally(5, Duration.ofSeconds(10)));
        Bucket bucket = Bucket.builder()
                .addLimit(limit)
                .build();

        for (int i = 0; i < 10; i++) {
            if (bucket.tryConsume(1)) {
                System.out.println("Запрос " + i + " разрешен");
            } else {
                System.out.println("Запрос " + i + " заблокирован");
            }
        }
    }
}

Плюсы: Гибкая настройка, распределенная поддержка, высокая производительность.
Минусы: Больше зависимостей, чем у Guava.

3. Resilience4j RateLimiter (для микросервисной архитектуры)

Resilience4j — это библиотека для обеспечения отказоустойчивости, в состав которой входит модуль RateLimiter. Она разработана с учетом принципов реактивного программирования и легко интегрируется с Spring Boot, Micrometer и другими инструментами.

Алгоритм: Использует Sliding Window (скользящее окно) на основе атомарных счетчиков. Поддерживает два режима: Atomic (блокирующий) и Semaphore (неблокирующий).

Пример с использованием Spring Boot:

import io.github.resilience4j.ratelimiter.RateLimiter;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;

import java.time.Duration;

public class Resilience4jExample {
    public static void main(String[] args) {
        RateLim                    

Рекомендаций