← Назад к вопросам

Как сделать ограничение запросов API?

2.0 Middle🔥 152 комментариев
#API и веб-протоколы

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ограничение запросов API: стратегии и реализация в PHP

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

Основные стратегии ограничения запросов

Токен-бакет (Token Bucket) — наиболее популярный алгоритм:

  • Система имеет "ведро" с фиксированным количеством токенов
  • Каждый запрос потребляет один токен
  • Токены пополняются с постоянной скоростью
  • Гибкость: позволяет обрабатывать всплески трафика

Фиксированное окно (Fixed Window):

  • Считает запросы в фиксированных временных интервалах (например, 100 запросов в минуту)
  • Проще в реализации, но возможны проблемы на границах окон

Скользящее окно (Sliding Window):

  • Учитывает запросы за последние N секунд
  • Более точное ограничение, но сложнее в реализации

Практическая реализация на PHP

Вариант 1: Использование Redis для распределенного ограничения

Для микросервисной архитектуры или кластерной среды Redis — оптимальный выбор:

<?php
class RateLimiter {
    private $redis;
    private $limit;
    private $window;
    
    public function __construct($limit = 100, $window = 60) {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
        $this->limit = $limit;
        $this->window = $window;
    }
    
    public function isAllowed($key) {
        $current = microtime(true);
        $windowStart = $current - $this->window;
        
        // Удаляем старые записи
        $this->redis->zRemRangeByScore($key, 0, $windowStart);
        
        // Считаем текущие запросы
        $requestCount = $this->redis->zCard($key);
        
        if ($requestCount < $this->limit) {
            // Добавляем новый запрос
            $this->redis->zAdd($key, $current, uniqid());
            $this->redis->expire($key, $this->window);
            return true;
        }
        
        return false;
    }
}

Вариант 2: Middleware-подход в Laravel

В современных PHP-фреймворках часто используют middleware:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Cache\RateLimiter;
use Symfony\Component\HttpFoundation\Response;

class ApiRateLimit {
    protected $limiter;
    
    public function __construct(RateLimiter $limiter) {
        $this->limiter = $limiter;
    }
    
    public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1) {
        $key = $this->resolveRequestSignature($request);
        
        if ($this->limiter->tooManyAttempts($key, $maxAttempts)) {
            return response()->json([
                'message' => 'Too many attempts',
                'retry_after' => $this->limiter->availableIn($key)
            ], Response::HTTP_TOO_MANY_REQUESTS);
        }
        
        $this->limiter->hit($key, $decayMinutes * 60);
        
        $response = $next($request);
        
        $response->headers->add([
            'X-RateLimit-Limit' => $maxAttempts,
            'X-RateLimit-Remaining' => $this->limiter->remaining($key, $maxAttempts)
        ]);
        
        return $response;
    }
}

Ключевые аспекты production-реализации

  1. Гибкость ограничений:

    • Разные лимиты для разных эндпоинтов
    • Отдельные правила для анонимных и аутентифицированных пользователей
    • Динамическое изменение лимитов на основе подписки/тарифа
  2. Информирование клиента:

    • HTTP-заголовки: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
    • Статус 429 (Too Many Requests) при превышении
    • Четкие сообщения об ошибках с временем восстановления
  3. Мониторинг и аналитика:

    • Логирование всех срабатываний ограничений
    • Метрики для анализа паттернов использования
    • Алёртинг при аномальной активности
  4. Обходные пути для легитимных случаев:

    • API-ключи с повышенными лимитами
    • Белые списки для доверенных IP-адресов
    • Механизм "burst" для кратковременных всплесков

Рекомендации по выбору подхода

  • Монолитное приложение: файловое кэширование или база данных
  • Распределенная система: Redis или Memcached
  • Высоконагруженные API: специализированные решения вроде Nginx rate limiting или API-гейтвеи (Kong, Apigee)
  • Гибридный подход: комбинация нескольких методов для разных слоев защиты

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

Наиболее надежное решение — многоуровневая защита: ограничение на уровне балансировщика нагрузки, промежуточного ПО приложения и бизнес-логики. Это обеспечивает защиту даже при частичных отказах компонентов системы.