Rate Limiting в Java: библиотеки, алгоритмы и реализация

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

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

Начать курс

Rate Limiting в Java: от теории до практической реализации

Rate Limiting (ограничение скорости запросов) — один из ключевых механизмов защиты и управления нагрузкой в современных распределённых системах. В Java эта задача решается как на уровне встроенных средств, так и с помощью специализированных библиотек. В этой статье мы разберём основные алгоритмы, популярные библиотеки и приведём рабочие примеры кода.

Зачем нужно Rate Limiting?

Rate Limiting позволяет:

  • Защитить API от злоупотреблений (DDoS, перебор паролей)
  • Равномерно распределять нагрузку на бэкенд
  • Соблюдать соглашения об уровне обслуживания (SLA)
  • Предотвращать превышение квот внешних сервисов

Основные алгоритмы Rate Limiting

Перед выбором библиотеки важно понимать, какие алгоритмы лежат в основе:

1. Token Bucket (Bucket4j, Guava)

Классический алгоритм. В "корзину" с определённой скоростью добавляются токены. Каждый запрос забирает один или несколько токенов. Если токенов нет — запрос отклоняется.

// Пример на псевдокоде
class TokenBucket {
    private int tokens;
    private long lastRefillTime;
    private final int capacity;
    private final double refillRate; // токенов в секунду

    synchronized boolean tryConsume() {
        refill();
        if (tokens > 0) {
            tokens--;
            return true;
        }
        return false;
    }
}

2. Sliding Window Log

Хранит временные метки последних запросов. При каждом новом запросе удаляет метки старше окна и проверяет, не превышен ли лимит. Точен, но требует памяти под хранение меток.

3. Fixed Window Counter

Простой счётчик на фиксированный интервал (например, 100 запросов в минуту). Сбрасывается каждую минуту. Уязвим для "пиковых" нагрузок на границах окна.

Популярные Java-библиотеки для Rate Limiting

1. Bucket4j

Bucket4j — зрелая библиотека, полностью реализующая алгоритм Token Bucket. Поддерживает распределённые сценарии через Redis, Hazelcast, JCache. Имеет Java 8+ API.

Установка (Maven):

<dependency>
    <groupId>com.github.vladimir-bukhtoyarov</groupId>
    <artifactId>bucket4j-core</artifactId>
    <version>8.7.0</version>
</dependency>

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

import io.github.bucket4j.*;
import java.time.Duration;

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

        for (int i = 0; i < 15; i++) {
            if (bucket.tryConsume(1)) {
                System.out.println("Запрос #" + i + " выполнен");
            } else {
                System.out.println("Запрос #" + i + " отклонён (лимит превышен)");
            }
        }
    }
}

2. Resilience4j RateLimiter

Часть популярного фреймворка для отказоустойчивости. Работает на основе SemaphoreBasedRateLimiter или AtomicRateLimiter. Легко интегрируется с Spring Boot.

Пример конфигурации:

import io.github.resilience4j.ratelimiter.*;
import java.time.Duration;

public class Resilience4jExample {
    public static void main(String[] args) {
        RateLimiterConfig config = RateLimiterConfig.custom()
                .limitForPeriod(5)                // 5 запросов
                .limitRefreshPeriod(Duration.ofSeconds(1)) // каждую секунду
                .timeoutDuration(Duration.ofMillis(100))
                .build();

        RateLimiter rateLimiter = RateLimiter.of("myService", config);

        for (int i = 0; i < 8; i++) {
            Runnable task = RateLimiter.decorateRunnable(rateLimiter, () -> {
                System.out.println("Запрос #" + i + " выполнен");
            });
            try {
                task.run();
            } catch (Exception e) {
                System.out.println("Запрос #" + i + " отклонён: " + e.getMessage());
            }
        }
    }
}

3. Google Guava RateLimiter

Встроенный в библиотеку Guava (Google). Простой, но не поддерживает распределённые сценарии. Работает на алгоритме Token Bucket с "предварительным потреблением" (burst).

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

public class GuavaRateLimiterExample {
    public static void main(String[] args) {
        // 2 запроса в секунду
        RateLimiter rateLimiter = Rate                    

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