Rate Limiting en PHP: protección de API y optimización de carga
\nRate limiting (limitación de velocidad de solicitudes) es un mecanismo crítico para cualquier aplicación web en PHP, especialmente para APIs públicas. Previene abusos, protege contra ataques DDoS, reduce la carga del servidor y garantiza una distribución justa de recursos entre usuarios. En este artículo, analizaremos en detalle las bibliotecas y herramientas populares para implementar rate limiting en PHP.
\n\nAlgoritmos principales de rate limiting
\nAntes de elegir una biblioteca, es importante comprender los algoritmos básicos:
\n- \n
- Token Bucket (Cubo de tokens) — el algoritmo más flexible. El cubo contiene N tokens, cada solicitud consume un token. Los tokens se regeneran a una velocidad determinada. \n
- Leaky Bucket (Cubo con fugas) — las solicitudes se procesan a una velocidad constante. Las solicitudes excedentes se descartan o se ponen en cola. \n
- Fixed Window (Ventana fija) — las solicitudes se cuentan en un intervalo fijo (ej. 60 segundos). Simple, pero puede permitir picos de carga en los límites de las ventanas. \n
- Sliding Window (Ventana deslizante) — algoritmo más preciso que considera solicitudes en una ventana de tiempo móvil. Utiliza registros o contadores con marcas de tiempo. \n
Bibliotecas populares para rate limiting en PHP
\n\n1. Symfony Rate Limiter (symfony/rate-limiter)
\nComponente oficial de Symfony, pero también funciona como biblioteca independiente. Soporta todos los algoritmos principales: Token Bucket, Fixed Window, Sliding Window. Ideal para proyectos en Symfony o Laravel.
\nuse Symfony\\Component\\RateLimiter\\RateLimiterFactory;\nuse Symfony\\Component\\RateLimiter\\Storage\\InMemoryStorage;\n\n$factory = new RateLimiterFactory([\n 'id' => 'api',\n 'policy' => 'token_bucket',\n 'limit' => 100,\n 'rate' => ['interval' => '1 minute'],\n], new InMemoryStorage());\n\n$limiter = $factory->create('user_123');\n\nif ($limiter->consume(1)->isAccepted()) {\n // Procesar solicitud\n} else {\n // Devolver 429 Too Many Requests\n header('HTTP/1.1 429 Too Many Requests');\n echo json_encode(['error' => 'Rate limit exceeded']);\n}\n\n2. nikic/FastRoute con middleware rate limiting
\nSolución ligera para proyectos sin frameworks. Utiliza una implementación PHP de Token Bucket con almacenamiento en Redis o Memcached.
\nclass RateLimitMiddleware {\n private $redis;\n private $maxRequests = 100;\n private $window = 60; // segundos\n\n public function handle($request, $next) {\n $key = 'rate_limit:' . $_SERVER['REMOTE_ADDR'];\n $current = $this->redis->incr($key);\n \n if ($current === 1) {\n $this->redis->expire($key, $this->window);\n }\n\n if ($current > $this->maxRequests) {\n return new Response('Too Many Requests', 429);\n }\n\n return $next($request);\n }\n}\n\n3. Laravel Rate Limiter (integrado)
\nEn Laravel, el rate limiting está integrado en el núcleo. Utiliza Redis o caché. Soporta limitadores con nombre y segmentación por usuarios.
\n// En RouteServiceProvider\nuse Illuminate\\Cache\\RateLimiting\\Limit;\nuse Illuminate\\Http\\Request;\n\nprotected function configureRateLimiting()\n{\n RateLimiter::for('api', function (Request $request) {\n return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());\n });\n}\n\n// En el controlador\npublic function index()\n{\n $executed = RateLimiter::attempt(\n 'send-message:'.$user->id,\n $perMinute = 5,\n function() {\n // Enviar mensaje\n }\n );\n \n if (! $executed) {\n return response('Too Many Attempts.', 429);\n }\n}\n\n4. PHP RateLimit (php-rateLimit/php-rateLimit)
\nBiblioteca unive
También en la biblioteca
Trabajo con Markdown en C++: bibliotecas, analizadores y herramientas
Monitoreo de aplicaciones Java: biblioteca Micrometer e integración con Prometheus
Biblioteca WebSocket Java: Tyrus — implementación de JSR 356 para tiempo real