Rate Limiting en Java : de la théorie à la mise en œuvre pratique
Le Rate Limiting (limitation du taux de requêtes) est l'un des mécanismes clés de protection et de gestion de la charge dans les systèmes distribués modernes. En Java, ce problème est résolu à la fois au niveau des outils intégrés et à l'aide de bibliothèques spécialisées. Dans cet article, nous examinerons les principaux algorithmes, les bibliothèques populaires et fournirons des exemples de code fonctionnels.
Pourquoi le Rate Limiting est-il nécessaire ?
Le Rate Limiting permet de :
- Protéger l'API contre les abus (DDoS, force brute de mots de passe)
- Répartir uniformément la charge sur le backend
- Respecter les accords de niveau de service (SLA)
- Empêcher le dépassement des quotas des services externes
Algorithmes principaux du Rate Limiting
Avant de choisir une bibliothèque, il est important de comprendre les algorithmes sous-jacents :
1. Token Bucket (Bucket4j, Guava)
Algorithme classique. Des jetons sont ajoutés à un "seau" à une vitesse définie. Chaque requête consomme un ou plusieurs jetons. S'il n'y a pas de jetons, la requête est rejetée.
// Exemple en pseudo-codeclass TokenBucket { private int tokens; private long lastRefillTime; private final int capacity; private final double refillRate; // jetons par seconde
synchronized boolean tryConsume() { refill(); if (tokens > 0) { tokens--; return true; } return false; }}2. Sliding Window Log
Stocke les horodatages des dernières requêtes. À chaque nouvelle requête, il supprime les horodatages plus anciens que la fenêtre et vérifie si la limite n'est pas dépassée. Précis, mais nécessite de la mémoire pour stocker les horodatages.
3. Fixed Window Counter
Compteur simple sur un intervalle fixe (par exemple, 100 requêtes par minute). Il est réinitialisé chaque minute. Vulnérable aux pics de charge aux limites de la fenêtre.
Bibliothèques Java populaires pour le Rate Limiting
1. Bucket4j
Bucket4j est une bibliothèque mature qui implémente entièrement l'algorithme Token Bucket. Elle prend en charge les scénarios distribués via Redis, Hazelcast, JCache. Elle dispose d'une API Java 8+.
Installation (Maven) :
<dependency> <groupId>com.github.vladimir-bukhtoyarov</groupId> <artifactId>bucket4j-core</artifactId> <version>8.7.0</version></dependency>Exemple d'utilisation :
import io.github.bucket4j.*;import java.time.Duration;
public class Bucket4jExample { public static void main(String[] args) { // Création d'un seau : 10 jetons, recharge de 1 jeton par seconde Bandwidth limit = Bandwidth.simple(10, Duration.ofSeconds(1)); Bucket bucket = Bucket4j.builder().addLimit(limit).build();
for (int i = 0; i < 15; i++) { if (bucket.tryConsume(1)) { System.out.println("Requête #" + i + " exécutée"); } else { System.out.println("Requête #" + i + " rejetée (limite dépassée)"); } } }}2. Resilience4j RateLimiter
Fait partie du framework populaire pour la résilience. Fonctionne sur la base de SemaphoreBasedRateLimiter ou AtomicRateLimiter. S'intègre facilement avec Spring Boot.
Exemple de configuration :
import io.github.resilience4j.ratelimiter.*;import java.time.Duration;
public class Resilience4jExample { public static void main(String[] args) { RateLimiterConfig config = RateLimiterConfig.custom() .limitForPeriod(5) // 5 requêtes .limitRefreshPeriod(Duration.ofSeconds(1)) // chaque seconde .timeoutDuration(Duration.ofMillis(100)) .build();
RateLimiter rateLimiter = RateLimiter.of("myService", config);
for (int i = 0; i < 8; i++) { Runnable task = R Aussi dans la bibliothèque
Tests en Swift (iOS/macOS) : frameworks et outils
Tower Rust : guide complet avec exemples concrets
Surveillance des applications Rust : la bibliothèque `tracing`