Limitación de tasa en Rust: bibliotecas governor, leaky-bucket y middleware para servidores web

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Limitación de tasa en Rust: revisión de bibliotecas y herramientas



La limitación de tasa (rate limiting) es un mecanismo crítico para proteger servicios web contra sobrecargas, ataques DDoS y abusos. En el ecosistema de Rust, hay varias bibliotecas maduras para implementar limitación de tasa: desde algoritmos de bajo nivel hasta middleware listos para usar en frameworks web populares. En este artículo, analizaremos tres enfoques clave: governor (algoritmo GCRA), leaky-bucket (cubo con fugas) y la integración con Actix/Axum.



1. Biblioteca governor — algoritmo GCRA



governor es la biblioteca de limitación de tasa más popular en Rust, basada en el Generic Cell Rate Algorithm (GCRA). Este algoritmo se utiliza en protocolos de red y permite configurar de manera flexible tanto la carga máxima como la velocidad promedio.



Características clave:

  • Soporte para múltiples claves (IP, User-Agent, clave API)
  • Burst (ráfaga de tráfico) configurable
  • Funcionamiento asíncrono mediante tokio o async-std
  • Seguridad para subprocesos sin bloqueos


Ejemplo de configuración de límite de 100 solicitudes por minuto con burst de 20:



use governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};use std::num::NonZeroU32;use std::time::Duration;

#[tokio::main]async fn main() { // Límite: 100 solicitudes por minuto, burst 20 let quota = Quota::with_period(Duration::from_secs(60)) .unwrap() .allow_burst(NonZeroU32::new(20).unwrap()); let limiter = DefaultKeyedRateLimiter::::new(quota); // Verificación para el usuario "user123" match limiter.check_key("user123") { Ok(_) => println!("Solicitud permitida"), Err(_) => println!("Límite excedido, estado 429"), }}


2. Biblioteca leaky-bucket — cubo con fugas



El algoritmo del cubo con fugas está implementado en la biblioteca leaky-bucket. Modela un cubo de agua que se llena con solicitudes y se vacía a una velocidad constante. Es adecuado para suavizar picos de carga.



Características:

  • Modelo simple: cubo con capacidad de N solicitudes
  • Velocidad de fuga: cantidad de solicitudes por segundo
  • Soporte para un máximo de solicitudes en espera


Ejemplo con límite de 5 solicitudes por segundo y cubo de 10:



use leaky_bucket::RateLimiter;use std::time::Duration;

#[tokio::main]async fn main() { let limiter = RateLimiter::builder() .initial(10) // cantidad inicial de tokens .max(10) // tamaño máximo del cubo .interval(Duration::from_millis(200)) // recarga cada 200 ms .build(); // Intento de obtener un token if limiter.try_acquire().is_ok() { println!("Solicitud procesada"); } else { println!("Cubo vacío, rechazado"); }}


3. Middleware para frameworks web



Los middleware listos para usar simplifican enormemente la integración de la limitación de tasa en servidores web con Actix y Axum.



Actix + governor



use actix_web::{web, App, HttpServer, HttpRequest, HttpResponse, middleware::from_fn};use governor::{DefaultKeyedRateLimiter, Quota};use std::num::NonZeroU32;use std::time::Duration;

async fn rate_limit_middleware( req: HttpRequest, limiter: web::Data<DefaultKeyedRateLimiter<String>>,) -> Result<HttpResponse, actix_web::Error> { let client_ip = req.peer_addr() .map(|addr| addr.to_string()) .unwrap_or_default(); match limiter.check_key(&client_ip) { Ok(_) => Ok(HttpResponse::Ok().body("OK")), Err(_) => Ok(HttpResponse::TooManyRequests().body("Too Many Requests")), }}

Recommendations