Rate Limiting в Kotlin: библиотеки и практические примеры

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

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

Начать курс

Rate Limiting в Kotlin: полное руководство по инструментам и библиотекам

Rate limiting (ограничение скорости запросов) — критически важный механизм для защиты веб-сервисов, API и микросервисов от перегрузок, DDoS-атак и неконтролируемого потребления ресурсов. В экосистеме Kotlin существует несколько мощных библиотек и встроенных инструментов для реализации throttling. В этой статье мы подробно разберём лучшие практики, популярные библиотеки и примеры кода на Kotlin.

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

Без ограничений клиент или злоумышленник может отправить тысячи запросов в секунду, что приведёт к:

  • Деградации производительности для всех пользователей
  • Перегрузке базы данных и внешних API
  • Увеличению затрат на облачную инфраструктуру
  • Нарушению SLA (Service Level Agreement)

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

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

  • Token Bucket (Токеновое ведро) — самый популярный алгоритм. Токены добавляются с постоянной скоростью, каждый запрос потребляет один токен. Если токены закончились — запрос отклоняется.
  • Leaky Bucket (Дырявое ведро) — запросы помещаются в очередь фиксированного размера и обрабатываются с постоянной скоростью. Избыточные запросы отбрасываются.
  • Sliding Window (Скользящее окно) — учитывает запросы за последний временной интервал (например, 60 секунд). Более точный, чем фиксированное окно.
  • Fixed Window (Фиксированное окно) — простейший алгоритм: лимит сбрасывается каждые N секунд. Уязвим для всплесков на границах окна.

Топ библиотек для Rate Limiting в Kotlin

1. Resilience4j — RateLimiter

Resilience4j — это лёгкая библиотека для обеспечения отказоустойчивости, вдохновлённая Netflix Hystrix. Она предоставляет модуль RateLimiter, который идеально подходит для Kotlin-приложений благодаря полной совместимости с корутинами и функциональному стилю.

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

implementation("io.github.resilience4j:resilience4j-kotlin:2.2.0")
implementation("io.github.resilience4j:resilience4j-ratelimiter:2.2.0")

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

import io.github.resilience4j.ratelimiter.RateLimiter
import io.github.resilience4j.ratelimiter.RateLimiterConfig
import io.github.resilience4j.kotlin.ratelimiter.executeSuspendFunction
import kotlinx.coroutines.delay
import java.time.Duration

// Создаём конфигурацию: 10 запросов в секунду
val config = RateLimiterConfig.custom()
    .limitForPeriod(10)
    .limitRefreshPeriod(Duration.ofSeconds(1))
    .timeoutDuration(Duration.ofMillis(500))
    .build()

val rateLimiter = RateLimiter.of("my-api-limiter", config)

suspend fun limitedApiCall(): String {
    return rateLimiter.executeSuspendFunction {
        // Ваш API-запрос
        delay(100)
        "Response from API"
    }
}

Преимущества:

  • Нативная поддержка Kotlin-корутин
  • Гибкая настройка таймаутов и лимитов
  • Мониторинг через Micrometer, Prometheus
  • Работает с Spring Boot, Ktor, Vert.x

2. Bucket4j — продвинутый Token Bucket

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

Установка:

implementation("com.github.vladimir-bukhtoyarov:bucket4j-core:8.7.0")
implementation("com.github.vladimir-bukhtoyarov:bucket4j-redis:8.7.0") // для распределённого режима

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

import io.github.bucket4j.Bandwidth
import io.github.bucket4j.Bucket
import io.github.bucket4j.Refill
import java.time.Duration

// Создаём bucket: 100 запросов в минуту с возможностью burst до 20
val bucket = Bucket.builder()
    .addLimit(Bandwidth.classic(100, Refill.greedy(100, Duration.ofMinutes(1))))
    .addLimit(Bandwidth.classic(20, Refill.intervally(20, Duration.ofSeconds(10))))
    .build()

fun handleRequest(): Boolean {                    

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