Rate Limiting API: Алгоритмы и реализация

Security2026-09-20TryQuickToolBox

Ваш API под атакой. Не изощрённых хакеров, а простого скрипта, который бомбардирует ваши эндпоинты тысячи раз в секунду, потребляя ресурсы и ухудшая сервис для легитимных пользователей. Без ограничения скорости один неправильно работающий клиент может обрушить всё приложение. Это руководство объясняет основные алгоритмы и показывает практические реализации в Node.js и Nginx для защиты вашего API.

Почему ограничение скорости важно

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

Помимо безопасности, ограничение скорости обеспечивает справедливое использование и помогает применять бизнес-правила, например, тарифные планы.

Алгоритмы ограничения скорости

Четыре алгоритма доминируют в ограничении скорости API. У каждого есть компромиссы в точности, использовании памяти и обработке всплесков.

1. Фиксированное окно

Подсчитывает запросы в фиксированных временных интервалах (например, 100 запросов в минуту). Когда окно сбрасывается, счётчик сбрасывается.

2. Скользящее окно

Отслеживает временные метки каждого запроса и подсчитывает, сколько попадает в последние N секунд. Это сглаживает всплески.

3. Маркерное ведро

Ведро содержит маркеры. Маркеры добавляются с фиксированной скоростью. Каждый запрос потребляет один маркер. Если ведро пусто, запрос отклоняется.

4. Дырявое ведро

Запросы попадают в очередь (ведро) и обрабатываются с постоянной скоростью. Если очередь заполнена, запросы отбрасываются.

АлгоритмОбработка всплесковПамятьСценарий использования
Фиксированное окноПлохоНизкаяПростые API
Скользящее окноХорошоСредняяОбщего назначения
Маркерное ведроОтличноСредняяAPI с допустимыми всплесками
Дырявое ведроНетСредняяСглаживание трафика

Реализация ограничения скорости в Node.js

Мы реализуем ограничитель скорости на основе маркерного ведра с использованием Express и Redis для распределённого состояния. Redis необходим, когда у вас несколько экземпляров сервера.

Шаг 1: Установите зависимости

npm install express redis

Шаг 2: Создайте middleware ограничителя скорости

const redis = require('redis');
const client = redis.createClient();

async function tokenBucketLimiter(req, res, next) {
  const key = `rate_limit:${req.ip}`;
  const capacity = 10; // max tokens
  const refillRate = 1; // tokens per second

  const now = Date.now();
  const data = await client.hGetAll(key);
  let tokens = data.tokens ? parseFloat(data.tokens) : capacity;
  let lastRefill = data.lastRefill ? parseInt(data.lastRefill) : now;

  // Refill tokens based on elapsed time
  const elapsed = (now - lastRefill) / 1000;
  tokens = Math.min(capacity, tokens + elapsed * refillRate);

  if (tokens < 1) {
    return res.status(429).json({ error: 'Too many requests' });
  }

  tokens -= 1;
  await client.hSet(key, {
    tokens: tokens.toString(),
    lastRefill: now.toString()
  });
  await client.expire(key, 60); // auto-cleanup

  next();
}

app.use(tokenBucketLimiter);

Этот middleware проверяет и обновляет количество маркеров атомарно. Для продакшена используйте транзакции Redis или скрипты Lua, чтобы избежать состояний гонки.

Реализация ограничения скорости в Nginx

Nginx предлагает встроенное ограничение скорости с модулем limit_req. Он использует алгоритм дырявого ведра.

Шаг 1: Определите зону ограничения скорости

В блоке http файла nginx.conf:

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

Это создаёт зону размером 10 МБ с именем api, которая допускает 10 запросов в секунду на IP.

Шаг 2: Примените ограничение

В вашем блоке location:

location /api/ {
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://backend;
}

burst=20 допускает короткие всплески до 20 запросов. nodelay обрабатывает всплесковые запросы немедленно, а не ставит их в очередь.

Лучшие практики ограничения скорости API

FAQ

В чём разница между ограничением скорости и троттлингом?

Ограничение скорости блокирует запросы сверх порога, тогда как троттлинг замедляет их (например, через очередь или задержку). Ограничение скорости бинарно; троттлинг постепенен.

Какой алгоритм ограничения скорости мне использовать?

Для большинства API маркерное ведро предлагает хороший баланс: позволяет всплески, но обеспечивает среднюю скорость. Если нужно строгое сглаживание, используйте дырявое ведро. Для простоты фиксированное окно подходит для низконагруженных API.

Как обрабатывать ограничение скорости для аутентифицированных и анонимных пользователей?

Применяйте более строгие ограничения к анонимным пользователям (например, по IP) и более щедрые к аутентифицированным (например, по API-ключу). Вы также можете реализовать многоуровневые ограничения на основе планов подписки.

Готовы проанализировать трафик вашего API? Используйте наш Nginx Log Analyzer для парсинга логов, выявления нарушений ограничений и оптимизации порогов.