Rate Limiting in Java: Von der Theorie zur praktischen Umsetzung
Rate Limiting (Begrenzung der Anfragegeschwindigkeit) ist einer der Schlüsselmechanismen zum Schutz und zur Laststeuerung in modernen verteilten Systemen. In Java wird diese Aufgabe sowohl mit integrierten Mitteln als auch mit spezialisierten Bibliotheken gelöst. In diesem Artikel behandeln wir die wichtigsten Algorithmen, beliebte Bibliotheken und geben funktionierende Codebeispiele.
Warum ist Rate Limiting notwendig?
Rate Limiting ermöglicht:
- Schutz der API vor Missbrauch (DDoS, Passwort-Erraten)
- Gleichmäßige Lastverteilung auf das Backend
- Einhaltung von Service-Level-Agreements (SLA)
- Verhinderung der Überschreitung von Kontingenten externer Dienste
Wichtige Algorithmen für Rate Limiting
Bevor Sie eine Bibliothek auswählen, ist es wichtig zu verstehen, welche Algorithmen zugrunde liegen:
1. Token Bucket (Bucket4j, Guava)
Klassischer Algorithmus. In einen "Eimer" werden mit einer bestimmten Rate Token hinzugefügt. Jede Anfrage entnimmt einen oder mehrere Token. Sind keine Token vorhanden, wird die Anfrage abgelehnt.
// Beispiel in Pseudocodeclass TokenBucket { private int tokens; private long lastRefillTime; private final int capacity; private final double refillRate; // Token pro Sekunde
synchronized boolean tryConsume() { refill(); if (tokens > 0) { tokens--; return true; } return false; }}2. Sliding Window Log
Speichert Zeitstempel der letzten Anfragen. Bei jeder neuen Anfrage werden Zeitstempel, die älter als das Fenster sind, gelöscht und geprüft, ob das Limit nicht überschritten wurde. Präzise, benötigt aber Speicher für die Zeitstempel.
3. Fixed Window Counter
Einfacher Zähler für ein festes Intervall (z. B. 100 Anfragen pro Minute). Wird jede Minute zurückgesetzt. Anfällig für "Spitzenlasten" an den Fenstergrenzen.
Beliebte Java-Bibliotheken für Rate Limiting
1. Bucket4j
Bucket4j ist eine ausgereifte Bibliothek, die den Token-Bucket-Algorithmus vollständig implementiert. Unterstützt verteilte Szenarien über Redis, Hazelcast, JCache. Bietet eine Java 8+ API.
Installation (Maven):
<dependency> <groupId>com.github.vladimir-bukhtoyarov</groupId> <artifactId>bucket4j-core</artifactId> <version>8.7.0</version></dependency>Anwendungsbeispiel:
import io.github.bucket4j.*;import java.time.Duration;
public class Bucket4jExample { public static void main(String[] args) { // Eimer erstellen: 10 Token, Auffüllung 1 Token pro Sekunde 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("Anfrage #" + i + " ausgeführt"); } else { System.out.println("Anfrage #" + i + " abgelehnt (Limit überschritten)"); } } }}2. Resilience4j RateLimiter
Teil des beliebten Frameworks für Ausfallsicherheit. Arbeitet auf Basis von SemaphoreBasedRateLimiter oder AtomicRateLimiter. Lässt sich einfach in Spring Boot integrieren.
Konfigurationsbeispiel:
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 Anfragen .limitRefreshPeriod(Duration.ofSeconds(1)) // jede Sekunde .timeoutDuration(Duration.ofMillis(100)) .build();
RateLimiter rateLimiter = RateLimiter.of("myService", config);
for (int i = 0; i < 8; i++) { Runnable task = R