Rate Limiting в PHP: Полное руководство по защите от перегрузок
Rate Limiting (ограничение частоты запросов) — это критически важный механизм защиты веб-приложений. Он предотвращает злоупотребление ресурсами сервера, защищает от DDoS-атак, брутфорса паролей и спама. В PHP существует несколько эффективных подходов и библиотек для реализации rate limiting. В этой статье мы рассмотрим лучшие инструменты, принципы работы и практические примеры.
Что такое Rate Limiting и зачем он нужен?
Rate Limiting устанавливает максимальное количество запросов, которое клиент (IP-адрес, пользователь или API-ключ) может выполнить за определённый промежуток времени. Основные цели:
- Защита от DDoS — предотвращение перегрузки сервера ботами
- Предотвращение брутфорса — ограничение попыток входа в систему
- Справедливое распределение ресурсов — равный доступ для всех пользователей
- Экономия серверных ресурсов — снижение нагрузки на базу данных и процессор
Популярные алгоритмы Rate Limiting
Перед выбором библиотеки важно понимать основные алгоритмы:
- Token Bucket (Токен-ведро) — накапливает токены с определённой скоростью, позволяет кратковременные всплески трафика
- Leaky Bucket (Дырявое ведро) — сглаживает трафик, обрабатывая запросы с постоянной скоростью
- Fixed Window (Фиксированное окно) — считает запросы за фиксированный интервал времени
- Sliding Window (Скользящее окно) — более точный вариант, учитывающий запросы в скользящем временном окне
Лучшие библиотеки для Rate Limiting в PHP
1. Symfony Rate Limiter
Официальный компонент Symfony, который можно использовать независимо от фреймворка. Поддерживает Redis, APCu и файловое хранилище.
composer require symfony/rate-limiter
Пример использования:
<?php
use Symfony\Component\RateLimiter\RateLimiterFactory;
use Symfony\Component\RateLimiter\Storage\InMemoryStorage;
$factory = new RateLimiterFactory([
'id' => 'login',
'policy' => 'token_bucket',
'limit' => 10,
'rate' => ['interval' => '1 minute'],
], new InMemoryStorage());
$limiter = $factory->create('user_123');
if ($limiter->consume()->isAccepted()) {
// Разрешить запрос
echo "Доступ разрешен";
} else {
// Отклонить запрос
http_response_code(429);
echo "Слишком много запросов";
}
?>
2. PHP RateLimiter (by bantu)
Легковесная библиотека для простых сценариев. Поддерживает Redis, Memcached и файлы.
composer require bantu/php-ratelimiter
Пример:
<?php
use bantu\RateLimiter\RateLimiterFactory;
$factory = new RateLimiterFactory();
$limiter = $factory->createRedisRateLimiter(
new \Predis\Client(),
'api_limit',
100, // лимит запросов
3600 // окно в секундах
);
if ($limiter->hit($_SERVER['REMOTE_ADDR'])) {
echo "Запрос принят";
} else {
http_response_code(429);
echo "Лимит исчерпан";
}
?>
3. GrahamCampbell/Laravel RateLimiter
Если вы работаете с Laravel, это нативное решение. Встроено в фреймворк начиная с версии 8.
<?php
use Illuminate\Support\Facades\RateLimiter;
// Определение лимитера в AppServiceProvider
RateLimiter::for('api', function ($job) {
return \Illuminate\Cache\RateLimiting\Limit::perMinute(60)->by($job->user->id ?: $job->ip());
});
// Использование в контроллере
public function store(Request $request)
{
if (RateLimiter::tooManyAttempts('send-message:'.$request->ip(), 5)) {
return response('Слишком много сообщений', 429);
}
RateLimiter::hit('send-message:'.$request->ip(), 60);
// Обработка сообщения
}
?>
Реализация Rate Limiting с Redis (без библиотек)
Если вы предпочитаете минималистичные решения, можно реализовать rate limiting с помощью Redis INCR и EXPIRE:
<?php
$redis = new Redis();
$redis->connect('127.0.0