Управление потоком запросов (англ. rate limiting throttling)

Узнай, как Rate Limiting защищает API от DDoS и перегрузок. Простые алгоритмы для стабильной работы твоего сервиса.

Бесплатная консультация юриста

+7 (800) -01-07-30

Реклама jurik.ru

Управление потоком запросов (англ․ rate limiting‚ throttling) – это набор техник и алгоритмов‚ позволяющих контролировать количество запросов‚
которые клиент может отправить к сервису за определённый промежуток времени․
Главная цель – защитить систему от перегрузок‚ DDoS‑атак‚ обеспечить справедливое распределение ресурсов и поддерживать предсказуемую производительность․

Почему это важно?

  • Предотвращение перегрузки серверов и падения сервисов․
  • Защита от мошеннических атак (DDoS‚ brute‑force)․
  • Гарантия качественного обслуживания для всех клиентов․
  • Снижение стоимости инфраструктуры за счёт более эффективного использования ресурсов․

Классификация подходов к ограничению частоты запросов

  1. Фиксированное окно (Fixed Window) – счётчик запросов сбрасывается в начале каждого интервала (например‚ 100 запросов в минуту)․
  2. Скользящее окно (Sliding Window) – более плавный контроль‚ учитывающий запросы за последние N секунд․
  3. Токенное ведро (Token Bucket) – позволяет «всплеск» (burst) запросов‚ но поддерживает среднюю пропускную способность․
  4. Протекающее ведро (Leaky Bucket) – запросы помещаются в очередь и «вытекают» с фиксированной скоростью‚ устраняя всплески․

Алгоритм Token Bucket

Самый популярный в микросервисных архитектурах․ Идея проста:

  • Ведро имеет capacity – максимальное количество токенов․
  • Токены пополняются с фиксированной скоростью refillRate (например‚ 10 токенов/сек)․
  • Каждый входящий запрос «забирает» один токен․ Если токенов нет – запрос отклоняется (HTTP 429) или ставится в очередь․

Плюсы

  • Поддерживает burst‑трафик (в начале можно обработать несколько запросов подряд)․
  • Лёгко масштабируется в распределённых системах (Redis‚ Hazelcast‚ etc․)․

Минусы

  • Требует точного учёта времени пополнения‚ иначе возможны «пробои» в ограничении․

Алгоритм Leaky Bucket

Ведро с «дыркой» – запросы помещаются в очередь‚ а из неё «вытекают» с постоянной скоростью․ Если очередь переполняется‚ новые запросы отбрасываются․

Реализация в популярных технологиях

Java – библиотека Bucket4j

Bucket4j предоставляет гибкую реализацию Token Bucket с поддержкой локального и распределённого хранилища (JCache‚ Redis‚ Hazelcast)․

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

public class RateLimiterExample {
 // Ведро: 100 токенов‚ пополнение 10 токенов/сек
 private final Bucket bucket = Bucket4j․builder
 ․addLimit(Bandwidth․classic(100‚ Refill․greedy(10‚ Duration․ofSeconds(1))))
 ․build;

 public boolean tryConsume {
 // Попытка взять один токен
 return bucket․tryConsume(1);
 }
}

Если tryConsume возвращает false‚ сервер должен вернуть HTTP 429 Too Many Requests и добавить заголовки:

  • X-Rate-Limit-Limit – общий лимит․
  • X-Rate-Limit-Remaining – оставшиеся токены․
  • X-Rate-Limit-Reset – время до восстановления токенов (сек)․

․NET Core – пакет AspNetCoreRateLimit

Поддерживает фиксированное окно‚ скользящее окно и токенное ведро․ Пример конфигурации в appsettings․json:

{
 "IpRateLimiting": {
 "EnableEndpointRateLimiting": true‚
 "StackBlockedRequests": false‚
 "RealIpHeader": "X-Real-IP"‚
 "ClientIdHeader": "X-ClientId"‚
 "GeneralRules": [
 {
 "Endpoint": "*"‚
 "Period": "1m"‚
 "Limit": 120
 }
 ]
 }
}

Redis + Lua – быстрый распределённый лимитер

Скрипт Lua гарантирует атомарность операции «пополнить‑и‑запросить»․

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local period = tonumber(ARGV[2])
local now = redis․call('TIME')[1]

local tokens = tonumber(redis․call('GET'‚ key) or limit)
local last = tonumber(redis․call('GET'‚ key․․':ts') or now)

local delta = math․max(0‚ now ― last)
local refill = math․floor(delta * (limit / period))
tokens = math․min(limit‚ tokens + refill)

if tokens < 1 then
 return 0
else
 tokens = tokens ─ 1
 redis․call('SET'‚ key‚ tokens)
 redis․call('SET'‚ key․․':ts'‚ now)
 return 1
end

Вызов из Java (Jedis) или из любого другого клиента позволяет реализовать глобальный лимит без единой точки отказа․

Защитные паттерны микросервисной архитектуры

  • RateLimiter – ограничивает количество запросов к сервису․
  • Bulkhead – изолирует ресурсы (пул потоков‚ соединений) для разных клиентов․
  • CircuitBreaker – размыкает цепочку при постоянных ошибках․
  • Timeout – ограничивает время ожидания ответа․
  • Fallback – предоставляет запасной ответ․

Лучшие практики внедрения

  1. Определите бизнес‑требования: какой уровень burst‑трафика допустим‚ какие клиенты имеют приоритет․
  2. Выберите алгоритм в зависимости от характера нагрузки:
    • Token Bucket – для публичных API с разрешёнными всплесками․
    • Leaky Bucket – если нужен строгий поток без burst‑ов․
    • Sliding Window – когда важна плавность и точность․
  3. Реализуйте распределённый лимитер (Redis‚ Hazelcast‚ Consul) если система состоит из нескольких инстансов․
  4. Возвращайте корректный HTTP‑статус 429 и заголовки X-Rate-Limit-* для информирования клиента․
  5. Логируйте и мониторьте метрики: количество отклонённых запросов‚ среднее время отклика‚ уровень заполнения ведра․
  6. Тестируйте под нагрузкой (JMeter‚ k6) с различными сценариями burst‑трафика․

Часто задаваемые вопросы (FAQ)

Что делать‚ если клиент получает 429 слишком часто?

Рекомендуется реализовать экспоненциальный back‑off на клиентской стороне и предоставить в ответе Retry-After с рекомендацией‚ когда повторить запрос․

Можно ли комбинировать несколько алгоритмов?

Да․ Часто используют Token Bucket для общего лимита и Leaky Bucket внутри отдельного микросервиса‚ чтобы сгладить пики․

Как учесть «периодический» трафик (например‚ ночные пики)?

Настройте несколько правил с разными Period и Limit (например‚ более высокий лимит в 02:00‑04:00) либо используйте динамический лимит‚ меняемый через конфигурационный сервис․

Эффективное управление потоком запросов – фундаментальная часть любой современной распределённой системы․ Выбор правильного алгоритма‚ его корректная реализация и интеграция с другими защитными паттернами позволяют избежать перегрузок‚ повысить надёжность и обеспечить предсказуемое качество сервиса для всех пользователей․


Контакты для обращений

Официальный сайт: https://www․example․com

Горячая линия: +7 (495) -23‑45‑67 (круглосуточно)

Номера телефонов:

  • Техническая поддержка – +7 (495) -23‑45‑68
  • Отдел продаж – +7 (495) -23‑45‑69
  • Служба безопасности – +7 (495) -23‑45‑70

Электронный адрес: support@example․com

Личный кабинет: https://www․example․com/login

Личный приём (для VIP‑клиентов): запись через форму здесь

График приёма:

  • Понедельник‑Пятница: 09:00 – 18:00
  • Суббота: 10:00 – 14:00
  • Воскресенье: выходной

Отделы:

  1. Отдел разработки
  2. Отдел эксплуатации
  3. Отдел качества (QA)
  4. Отдел клиентского сервиса
  5. Отдел аналитики и мониторинга

Руководство:

  • Генеральный директор – Иванов И․И․
  • Технический директор – Петров П․П;
  • Директор по клиентскому сервису – Сидорова С․С․

Отзывы клиентов:

«Система ограничения запросов от Example Corp․ позволила нам стабильно обслуживать 1 млн запросов в сутки без падений․ Очень благодарны за гибкую настройку Token Bucket!» – ООО «ТехноСервис»

«Поддержка быстро реагирует‚ а личный кабинет упрощает управление лимитами в реальном времени․» – Алексей К․