Rate Limiting en Rust: gestión eficiente de la carga
\n\nRate limiting (limitación de la frecuencia de solicitudes) es un mecanismo clave para la protección y optimización de servicios web, API y aplicaciones de red. En el ecosistema de Rust existen varias bibliotecas maduras que implementan diferentes algoritmos: desde el clásico token bucket hasta métodos adaptativos modernos. En este artículo analizaremos tres bibliotecas principales: governor, leaky-bucket y ratelimit, con ejemplos de código y recomendaciones para su elección.
1. Biblioteca governor: el estándar de oro
\n\ngovernor es la biblioteca más popular y flexible para rate limiting. Implementa el algoritmo Generic Cell Rate Algorithm (GCRA), que garantiza el cumplimiento preciso de los límites con una latencia mínima. Admite modos síncrono y asíncrono, middleware para Actix-web, Axum y Rocket.
\n\nEjemplo básico con governor
\nuse governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};\nuse std::num::NonZeroU32;\nuse std::time::Duration;\n\nfn main() {\n // Permitimos 5 solicitudes por segundo\n let quota = Quota::per_second(NonZeroU32::new(5).unwrap());\n let limiter = RateLimiter::direct(quota);\n\n for i in 0..10 {\n match limiter.check() {\n Ok(_) => println!("Solicitud {} permitida", i),\n Err(_) => println!("Solicitud {} rechazada (rate limit)", i),\n }\n std::thread::sleep(Duration::from_millis(100));\n }\n}\n\nVariante asíncrona con espera
\nuse governor::{Quota, RateLimiter};\nuse std::num::NonZeroU32;\nuse tokio::time::{sleep, Duration};\n\n#[tokio::main]\nasync fn main() {\n let limiter = RateLimiter::direct(Quota::per_second(\n NonZeroU32::new(2).unwrap(),\n ));\n\n for i in 0..5 {\n limiter.until_ready().await;\n println!("Solicitud {} procesada", i);\n sleep(Duration::from_millis(300)).await;\n }\n}\n\nCaracterísticas clave de governor:
\n- \n
- Soporte para límites por clave (por IP, por usuario) mediante
KeyedRateLimiter\n - Integración con middleware
towerpara servidores HTTP \n - Estrategias configurables: espera, rechazo, desaceleración adaptativa \n
- Consumo mínimo de memoria (un contador atómico por limitador) \n
2. Biblioteca leaky-bucket: simplicidad y fiabilidad
\n\nleaky-bucket implementa el algoritmo clásico del «cubo con fugas». Es ideal para suavizar picos de carga cuando se necesita garantizar un flujo uniforme de solicitudes. La biblioteca es ligera y no requiere dependencias externas.
\n\nEjemplo con leaky-bucket
\nuse leaky_bucket::RateLimiter;\nuse std::time::Duration;\n\n#[tokio::main]\nasync fn main() {\n let limiter = RateLimiter::builder()\n .initial(10) // reserva inicial de tokens\n .interval(Duration::from_secs(1)) // intervalo de recarga\n .refill(5) // cuántos tokens agregar por intervalo\n .max(20) // número máximo de tokens\n .build();\n\n for i in 0..15 {\n limiter.acquire_one().await;\n println!("Solicitud {} completada", i);\n }\n}\n\nCaracterísticas de leaky-bucket:
\n- \n
- Soporte para API asíncrona y bloqueante \n
- Posibilidad de configurar el modo «burst» (ráfagas cortas) \n
- Liberación automática de tokens durante la inactividad \n
3. Biblioteca ratelimit: enfoque minimalista
\n\nratelimit es la biblioteca más simple, que implementa una ventana deslizante con intervalos fijos. Es adecuada para escenarios sencillos donde no se necesita alta precisión.
\n\nEjemplo con ratelimit
\nuse ratelimit::Ratelimiter;\nuse std::time::Duration;\n\nfn main() {\n let mut limiter = Ratelimiter::builder(10, Duration::from_secs(1))\n . También en la biblioteca
Cliente HTTP para JavaScript (Node.js): top bibliotecas para trabajar con API
Trabajo con CSV en C# (.NET): bibliotecas y ejemplos
Cliente OAuth para C++: biblioteca liboauth para autorización