Rate Limiting in Kotlin: Bibliotheken und Implementierung

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Rate Limiting in Kotlin: Bibliotheken, Strategien und praktische Beispiele

\n\n

Rate Limiting (Begrenzung der Anfragegeschwindigkeit) ist ein kritischer Mechanismus zum Schutz von APIs, Microservices und Webanwendungen vor übermäßiger Last, DDoS-Angriffen und zufälligen Traffic-Spitzen. Im Kotlin-Ökosystem, das auf der JVM läuft, gibt es mehrere ausgereifte Bibliotheken, die eine flexible Implementierung dieser Logik ermöglichen. In diesem Artikel betrachten wir drei Hauptansätze und Werkzeuge: Bucket4j, Resilience4j und den integrierten RateLimiter aus Guava.

\n\n

1. Bucket4j – Fortschrittliche Token-Bucket-Implementierung

\n\n

Bucket4j ist eine Java-Bibliothek, die perfekt mit Kotlin kompatibel ist. Sie implementiert den Token-Bucket-Algorithmus (Token-Eimer) und unterstützt sowohl lokale als auch verteilte Begrenzung (über Redis, Hazelcast, Infinispan).

\n\n

Wichtige Funktionen:

\n
    \n
  • Konfiguration der Token-Anzahl und ihrer Auffüllrate.
  • \n
  • Unterstützung von Bursts (kurzzeitigen Spitzen) durch Token-Akkumulation.
  • \n
  • Arbeit in einer Multithread-Umgebung ohne Sperren.
  • \n
  • Integration mit Spring Boot über den Starter bucket4j-spring-boot-starter.
  • \n
\n\n

Einfaches Beispiel für einen Rate Limiter in 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 Anfragen pro Minute, mit der Möglichkeit, bis zu 20 Token zu akkumulieren\n    val limit = Bandwidth.classic(20, Refill.greedy(10, Duration.ofMinutes(1)))\n    val bucket = Bucket.builder()\n        .addLimit(limit)\n        .build()\n\n    // Verfügbarkeit eines Tokens prüfen\n    if (bucket.tryConsume(1)) {\n        println("✅ Anfrage erlaubt")\n    } else {\n        println("❌ Limit überschritten, bitte später erneut versuchen")\n    }\n}
\n\n

Für verteilte Szenarien (z. B. mehrere Microservice-Instanzen) verwenden Sie Bucket4j mit 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 als Teil des Circuit Breaker

\n\n

Resilience4j ist eine beliebte Bibliothek für Ausfallsicherheit in Java/Kotlin, die nicht nur einen Rate Limiter, sondern auch Circuit Breaker, Retry und Bulkhead umfasst. Ihr Modul RateLimiter basiert auf dem Sliding-Window-Algorithmus (gleitendes Fenster).

\n\n

Besonderheiten:

\n
    \n
  • Einfache Integration mit Kotlin-Koroutinen über suspend-Funktionen.
  • \n
  • Konfiguration des Fensterzeitraums und des Anfragelimit.
  • \n
  • Flexible Fehlerbehandlung: Ausnahme auslösen, Fallback oder Warten.
  • \n
\n\n

Beispiel mit Koroutinen:

\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 Anfragen\n    .limitRefreshPeriod(Duration.ofSeconds(1)) // pro 1 Sekunde\n    .timeoutDuration(Duration.ofMillis(500))   // Timeout für Wartezeit\n    .build()\n\nval rateLimiter = RateLimiter.of("api-limiter", config)\n\nsuspend fun fetchData(): String {\n    return awaitRateLimiter(rateLimiter) {\n        // Ihr API-Aufruf\n        "Daten empfangen"\n    }\n}\n\nfun main() = runBlocking {\n    val result = fetchData()\n    p                    

Empfehlungen