Rate Limiting en Rust : gestion efficace de la charge
\n\nLe rate limiting (limitation de la fréquence des requêtes) est un mécanisme clé pour la protection et l'optimisation des services web, API et applications réseau. Dans l'écosystème Rust, il existe plusieurs bibliothèques matures implémentant différents algorithmes : du classique token-bucket aux méthodes adaptatives modernes. Dans cet article, nous analyserons trois bibliothèques principales : governor, leaky-bucket et ratelimit, avec des exemples de code et des recommandations pour choisir.
1. Bibliothèque governor — l'étalon-or
\n\ngovernor est la bibliothèque la plus populaire et la plus flexible pour le rate limiting. Elle implémente l'algorithme Generic Cell Rate Algorithm (GCRA), qui garantit le respect précis des limites avec un délai minimal. Elle prend en charge les modes synchrone et asynchrone, ainsi que les middlewares pour Actix-web, Axum et Rocket.
\n\nExemple de base avec governor
\nuse governor::{DefaultKeyedRateLimiter, Quota, RateLimiter};\nuse std::num::NonZeroU32;\nuse std::time::Duration;\n\nfn main() {\n // Autoriser 5 requêtes par seconde\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!("Requête {} autorisée", i),\n Err(_) => println!("Requête {} rejetée (rate limit)", i),\n }\n std::thread::sleep(Duration::from_millis(100));\n }\n}\n\nVariante asynchrone avec attente
\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!("Requête {} traitée", i);\n sleep(Duration::from_millis(300)).await;\n }\n}\n\nFonctionnalités clés de governor :
\n- \n
- Prise en charge des limites par clé (par IP, par utilisateur) via
KeyedRateLimiter\n - Intégration avec le middleware
towerpour les serveurs HTTP \n - Stratégies configurables : attente, rejet, ralentissement adaptatif \n
- Consommation mémoire minimale (un compteur atomique par limiteur) \n
2. Bibliothèque leaky-bucket — simplicité et fiabilité
\n\nleaky-bucket implémente l'algorithme classique du « seau percé ». Il est idéal pour lisser les pics de charge lorsqu'il faut garantir un flux de requêtes uniforme. La bibliothèque est légère et ne nécessite pas de dépendances externes.
\n\nExemple avec 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) // réserve initiale de jetons\n .interval(Duration::from_secs(1)) // intervalle de recharge\n .refill(5) // nombre de jetons ajoutés par intervalle\n .max(20) // nombre maximum de jetons\n .build();\n\n for i in 0..15 {\n limiter.acquire_one().await;\n println!("Requête {} exécutée", i);\n }\n}\n\nCaractéristiques de leaky-bucket :
\n- \n
- Prise en charge de l'API asynchrone et bloquante \n
- Possibilité de configurer le mode « burst » (pics temporaires) \n
- Libération automatique des jetons en période d'inactivité \n
3. Bibliothèque ratelimit — approche minimaliste
\n\nratelimit est la bibliothèque la plus simple, implémentant une fenêtre glissante avec des intervalles fixes. Elle convient aux scénarios simples où une grande précision n'est pas nécessaire.
\n\nExemple avec ratelimit
\nuse ratelimit::Ratelimiter;\nuse std::time::Duration;\n\nfn main() {\n let mut limiter = Ratelimiter::builder(10, Duration::from_secs(1))\n . Aussi dans la bibliothèque
Travail avec les dates en JavaScript (Node.js) : bibliothèques populaires
Configuration des applications Rust : bibliothèques config, envy et dotenvy
Conteneur d'injection de dépendances pour Kotlin : Koin vs Kodein vs Dagger
Parsing HTML en TypeScript : bibliothèques, outils et exemples de code