Rate Limiting en Kotlin : bibliothèques et implémentation

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Rate Limiting en Kotlin : bibliothèques, stratégies et exemples pratiques

\n\n

Le rate limiting (limitation du débit des requêtes) est un mécanisme essentiel pour protéger les API, les microservices et les applications web contre les charges excessives, les attaques DDoS et les pics de trafic soudains. Dans l'écosystème Kotlin, fonctionnant sur la JVM, il existe plusieurs bibliothèques matures qui permettent de mettre en œuvre cette logique de manière flexible. Dans cet article, nous allons analyser trois approches et outils principaux : Bucket4j, Resilience4j et le RateLimiter intégré de Guava.

\n\n

1. Bucket4j — implémentation avancée du Token Bucket

\n\n

Bucket4j est une bibliothèque Java, parfaitement compatible avec Kotlin. Elle implémente l'algorithme Token Bucket (seau de jetons) et prend en charge la limitation à la fois locale et distribuée (via Redis, Hazelcast, Infinispan).

\n\n

Fonctionnalités clés :

\n
    \n
  • Configuration du nombre de jetons et de leur vitesse de régénération.
  • \n
  • Prise en charge des « bursts » (pics temporaires) grâce à l'accumulation de jetons.
  • \n
  • Fonctionnement en environnement multithread sans blocage.
  • \n
  • Intégration avec Spring Boot via le starter bucket4j-spring-boot-starter.
  • \n
\n\n

Exemple simple de rate limiter en Kotlin :

\n
import io.github.bucket4j.Bandwidth\nimport io.github.bucket4j.Bucket\nimport io.github.bucket4j.Refill\nimport java.time.Duration\n\nfun main() {\n    // 10 requêtes par minute, avec possibilité d'accumuler jusqu'à 20 jetons\n    val limit = Bandwidth.classic(20, Refill.greedy(10, Duration.ofMinutes(1)))\n    val bucket = Bucket.builder()\n        .addLimit(limit)\n        .build()\n\n    // Vérifier la disponibilité d'un jeton\n    if (bucket.tryConsume(1)) {\n        println("✅ Requête autorisée")\n    } else {\n        println("❌ Limite dépassée, réessayez plus tard")\n    }\n}
\n\n

Pour un scénario distribué (par exemple, plusieurs instances d'un microservice), utilisez Bucket4j avec Redis :

\n
import io.github.bucket4j.distributed.proxy.ProxyManager\nimport io.github.bucket4j.redis.lettuce.Bucket4jLettuce\nimport io.lettuce.core.RedisClient\n\nval redisClient = RedisClient.create("redis://localhost:6379")\nval proxyManager: ProxyManager<String> = Bucket4jLettuce\n    .builder(redisClient)\n    .build()\n\nval bucket = proxyManager.builder()\n    .build("user:123", Bucket4jConfiguration(\n        Bandwidth.classic(100, Refill.intervally(100, Duration.ofMinutes(1)))\n    ))\n
\n\n

2. Resilience4j — RateLimiter comme composant du Circuit Breaker

\n\n

Resilience4j est une bibliothèque de résilience populaire pour Java/Kotlin, incluant non seulement un rate limiter, mais aussi un circuit breaker, retry, bulkhead. Son module RateLimiter fonctionne sur la base de l'algorithme Sliding Window (fenêtre glissante).

\n\n

Caractéristiques :

\n
    \n
  • Intégration facile avec les coroutines Kotlin via les fonctions suspend.
  • \n
  • Configuration de la période de la fenêtre et de la limite de requêtes.
  • \n
  • Gestion flexible des échecs : retour d'exception, fallback ou attente.
  • \n
\n\n

Exemple avec les coroutines :

\n
import io.github.resilience4j.ratelimiter.RateLimiter\nimport io.github.resilience4j.ratelimiter.RateLimiterConfig\nimport io.github.resilience4j.kotlin.ratelimiter.awaitRateLimiter\nimport java.time.Duration\nimport kotlinx.coroutines.runBlocking\n\nval config = RateLimiterConfig.custom()\n    .limitForPeriod(10)           // 10 requêtes\n    .limitRefreshPeriod(Duration.ofSeconds(1)) // par seconde\n    .timeoutDuration(Duration.ofMillis(500))   // délai d'attente\n    .build()\n\nval rateLimiter = RateLimiter.of("api-limiter", config)\n\nsuspend fun fetchData(): String {\n    return awaitRateLimiter(rateLimiter) {\n        // Votre appel API\n        "Données reçues"\n    }\n}\n\nfun main() = runBlocking {\n    val result = fetchData()\n    p                    

Recommendations