Содержание

Rate limiting — это ограничение количества запросов, которое клиент может сделать за единицу времени. Оно защищает API от перегрузки, перебора паролей, парсинга и ошибок в чужих интеграциях, которые случайно шлют тысячи запросов в секунду. Лимиты ставят по пользователю, ключу API или IP-адресу, а при превышении сервер отвечает кодом 429.

Разберём, зачем нужны лимиты, какие бывают алгоритмы, какие значения ставить и как правильно сообщать клиенту о превышении.

Зачем ограничивать частоту запросов?

Ограничение частоты нужно, чтобы один клиент не мог занять все ресурсы сервера и навредить остальным. Без лимитов достаточно одного зациклившегося скрипта партнёра или бота, перебирающего пароли, чтобы сайт замедлился для всех.

От чего защищают лимиты:

  • перебор паролей и кодов — злоумышленник не сможет проверять тысячи вариантов;
  • парсинг — конкуренты не выгрузят каталог за минуту;
  • спам — регистрации, формы обратной связи и отправка SMS ограничены;
  • ошибки интеграций — бесконечный цикл в чужом коде не положит ваш сервер;
  • дорогие операции — генерация отчётов и запросы к платным API под контролем.

Про другие уязвимости — в статье OWASP Top 10 простыми словами.

Какие бывают алгоритмы ограничения?

Основные алгоритмы — фиксированное окно, скользящее окно и «ведро с токенами». Они отличаются тем, как ведут себя на границе интервалов и разрешают ли короткие всплески активности.

Алгоритм Как работает Плюсы Минусы
Фиксированное окно Счётчик сбрасывается каждую минуту Простой, дешёвый Двойной всплеск на границе окон
Скользящее окно Считает запросы за последние N секунд Точнее Чуть дороже по памяти
Token bucket Токены пополняются с постоянной скоростью Разрешает короткие всплески Сложнее объяснить клиентам

Счётчики обычно хранят в Redis: операции атомарные, быстрые и общие для всех серверов приложения. Подробнее — в статье Redis в веб-проекте.

Плотное движение машин на шоссе Фото: Unsplash

Какие лимиты ставить на разные операции?

Лимиты ставят отдельно для каждого типа операции: чтение каталога может быть почти безлимитным, а вход, регистрация и отправка кодов — строго ограничены. Ключ лимита выбирают по смыслу: для авторизованных — пользователь или ключ API, для анонимных — IP-адрес.

RateLimiter::for('login', function (Request $request) {
    return [
        Limit::perMinute(5)->by($request->input('email')),
        Limit::perMinute(20)->by($request->ip()),
    ];
});

RateLimiter::for('api', function (Request $request) {
    return $request->user()
        ? Limit::perMinute($request->user()->plan->rate_limit)->by($request->user()->id)
        : Limit::perMinute(30)->by($request->ip());
});

Ориентиры для старта:

  1. Вход и восстановление пароля — несколько попыток в минуту на аккаунт и отдельный лимит на IP.
  2. Отправка SMS и писем — один код в минуту и небольшой дневной лимит на номер.
  3. Публичный API — лимит по ключу и тарифу, понятный и описанный в документации.
  4. Тяжёлые операции — экспорт и отчёты через очередь с ограничением на количество одновременных задач.

Как сообщать клиенту о превышении лимита?

О превышении сообщают ответом с кодом 429 Too Many Requests и заголовками, по которым клиент поймёт, когда можно повторить запрос. Хорошо спроектированный клиент читает эти заголовки и сам снижает темп, а не долбит сервер повторами.

HTTP/1.1 429 Too Many Requests
Retry-After: 30
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30

Опишите лимиты в документации API — как это сделать, мы разбирали в статье документация API и OpenAPI. Для клиентов, которые повторяют запросы, важна идемпотентность — подробнее в материале идемпотентность платежей и вебхуков.

Какие ошибки встречаются при внедрении лимитов?

Самая частая ошибка — лимит только по IP: за одним адресом может сидеть целый офис или мобильный оператор, и честные пользователи начинают получать отказы. Вторая — лимиты включают сразу в режиме блокировки, не посмотрев на реальную нагрузку.

  • лимит только по IP для авторизованных пользователей;
  • одинаковый лимит на чтение и на дорогие операции;
  • нет исключений для своих сервисов и мониторинга;
  • счётчики в памяти одного сервера, а серверов несколько;
  • ответ 500 или 403 вместо 429 — клиент не понимает, что делать.

Коротко

  • Rate limiting защищает от перегрузки, перебора, парсинга и ошибок интеграций.
  • Алгоритмы: фиксированное окно, скользящее окно, token bucket; счётчики — в Redis.
  • Лимиты различаются по операциям: строгие на вход и SMS, мягкие на чтение.
  • Ключ лимита — пользователь или ключ API, для анонимов — IP.
  • При превышении — код 429 и заголовки с временем повтора.

Частые вопросы

  • Защитит ли rate limiting от DDoS?

    Только от небольших атак и злоупотреблений. От серьёзного DDoS защищают на уровне сети и CDN — специализированные сервисы фильтрации трафика, до того как запросы дойдут до приложения.

  • Как выбрать конкретные значения лимитов?

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

  • Где лучше ограничивать запросы — в приложении или на балансировщике?

    Лучше на обоих уровнях. Балансировщик или CDN отсекает грубый поток по IP, а приложение ставит точные лимиты по пользователю, тарифу и типу операции.