API Rate Limiting Implementierung
API Rate Limiting in verteilten Systemen erfordert konsistente Zustandsverwaltung, die richtige Algorithmuswahl und eine klare Kommunikation mit Clients.
Kompakte Beschreibung
API Rate Limiting Implementierung beschreibt die technische Umsetzung von Begrenzungen für Anfragen an eine API. In verteilten Systemen muss das Limit über alle Instanzen hinweg konsistent gelten, was einen zentralen Speicher wie Redis oder eine Datenbank erfordert. Die wichtigsten Algorithmen sind Fixed Window, Sliding Window, Token Bucket und Leaky Bucket. Jeder Algorithmus hat unterschiedliche Eigenschaften bezüglich Fairness, Burst-Verhalten und Implementierungsaufwand. Bei der Implementierung müssen entscheidende Details wie die Identifikation des Clients, atomare Operationen, Header für die Statusanzeige, Fehlerbehandlung mit 429 und Retry-After, sowie die Wahl der richtigen Limits berücksichtigt werden. Rate Limiting sollte nicht nur im Anwendungscode, sondern auch im API Gateway oder Load Balancer konfiguriert werden können, um Schutz auf mehreren Ebenen zu bieten.
Wichtige Komponenten
Client-Identifikation
Rate Limiting benötigt eine eindeutige Identifikation des Clients. Dazu können API Keys, Nutzer-IDs, IP-Adressen oder Kombinationen aus mehreren Faktoren verwendet werden. Für authentifizierte Clients ist die Nutzer-ID meist die beste Wahl, da IP-Adressen sich ändern und mehrere Clients hinter einer IP teilen können.
Fixed Window Implementierung
Fixed Window zählt Anfragen in festen Zeitfenstern. In Redis kann ein Zähler pro Fenster und Client gespeichert werden. Der Zähler wird bei der ersten Anfrage im Fenster erstellt und läuft nach Ablauf der Zeit ab. Überschreitet der Zähler das Limit, wird die Anfrage abgelehnt.
Sliding Window Implementierung
Sliding Window ist fairer als Fixed Window, aber komplexer. Eine Variante ist Sliding Window Log, bei dem für jeden Client eine Liste von Zeitstempeln der letzten Anfragen gespeichert wird. Anfragen, die außerhalb des Fensters liegen, werden entfernt. Ist die Anzahl der verbleibenden Anfragen höher als das Limit, wird die Anfrage abgelehnt.
Token Bucket Implementierung
Token Bucket ist ein häufig verwendeter Algorithmus. Ein Bucket hat eine maximale Kapazität und wird mit Token mit konstanter Rate aufgefüllt. Jede Anfrage verbraucht ein Token. Ist der Bucket leer, wird die Anfrage abgelehnt oder verzögert. Redis eignet sich gut für Token Bucket mit Lua-Skripten für atomare Operationen.
Leaky Bucket Implementierung
Leaky Bucket verarbeitet Anfragen mit konstanter Rate. Anfragen werden in einer Warteschlange zwischengespeichert und gleichmäßig abgearbeitet. er Algorithmus ist gut für gleichmäßige Verarbeitung, kann aber zu Wartezeiten und Auswurf bei voller Queue führen.
Redis für verteiltes Rate Limiting
Redis bietet schnelle atomare Operationen und TTL, was es ideal für Rate Limiting macht. Lua-Skripte ermöglichen es, mehrere Befehle atomar auszuführen. Redis Cluster oder Redis Sentinel sorgen für Hochverfügbarkeit. Bei sehr hohen Anforderungen kann Redis als zentraler Bottleneck auftreten, weshalb Caching oder lokale Proxy-Caches ergänzt werden können.
Atomare Operationen
Rate Limiting muss atomar sein, um Race Conditions zu vermeiden. Wenn mehrere Anfragen gleichzeitig prüfen, ob noch Limit verfügbar ist, darf das Limit nicht überschritten werden. Lua-Skripte in Redis oder Transaktionen in Datenbanken helfen, Atomarität zu gewährleisten.
Header für Statusanzeige
Clients sollten über ihren aktuellen Status informiert werden. Header wie X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset sind weit verbreitet. Alternativ kann das RFC-RateLimit-Schema verwendet werden. Diese Header ermöglichen es Clients, ihre Anfragerate anzupassen.
Fehlerbehandlung mit 429
Wenn das Limit überschritten ist, antwortet die API mit 429 Too Many Requests. Der Retry-After Header sollte angeben, wann der Client es erneut versuchen darf. Die Fehlerantwort sollte nach RFC 7807 Problem Details formatiert sein und keine Interna enthalten.
Per-Endpoint und Per-User Limits
Unterschiedliche Endpunkte haben unterschiedliche Kosten. Schreiboperationen und teure Abfragen sollten strengere Limits haben als einfache Leseoperationen. Ebenso können unterschiedliche Nutzergruppen unterschiedliche Limits erhalten, beispielsweise kostenlose und zahlende Kunden.
Rate Limiting im API Gateway
API Gateways wie Kong, Nginx oder AWS API Gateway bieten eingebautes Rate Limiting. Sie schützen die API, bevor Anfragen das Backend erreichen. Gateways sind besonders effektiv für globale Limits und einfache Regeln, während Anwendungscode komplexere, nutzerspezifische Regeln umsetzen kann.
Praxisbeispiel
Ein Node.js Service implementiert Token Bucket Rate Limiting mit Redis.
const redis = require('redis');
const client = redis.createClient();
const LIMIT = 100;
const WINDOW_SECONDS = 60;
async function isAllowed(clientId) {
const key = `rate_limit:${clientId}`;
const lua = `
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local current = redis.call('GET', key)
if current == false then
current = 0
end
current = tonumber(current)
if current >= limit then
return 0
end
redis.call('INCR', key)
if current == 0 then
redis.call('EXPIRE', key, window)
end
return 1
`;
const result = await client.eval(lua, { keys: [key], arguments: [String(LIMIT), String(WINDOW_SECONDS)] });
return result === 1;
}
Middleware im Express:
async function rateLimit(req, res, next) {
const clientId = req.user?.id || req.ip;
const allowed = await isAllowed(clientId);
if (!allowed) {
res.set('Retry-After', String(WINDOW_SECONDS));
return res.status(429).json({
type: 'https://api.example.com/problems/rate-limit-exceeded',
title: 'Rate Limit überschritten',
status: 429,
detail: `Du hast das Limit von ${LIMIT} Anfragen pro ${WINDOW_SECONDS} Sekunden überschritten.`
});
}
next();
}
Dieser Ansatz ist atomar, funktioniert über mehrere Server-Instanzen hinweg und kommuniziert Limits klar an den Client.
FAQ: API Rate Limiting Implementierung
1. Wie identifiziert man einen Client für Rate Limiting?
2. Warum ist Redis für Rate Limiting geeignet?
3. Was ist ein Token Bucket in der Implementierung?
4. Was ist atomares Rate Limiting?
5. Was ist ein Sliding Window Log?
6. Was ist Fixed Window?
7. Was ist Leaky Bucket?
8. Was ist Race Condition beim Rate Limiting?
9. Welche Header sollten bei Rate Limiting gesetzt werden?
10. Was ist 429 Too Many Requests?
11. Sollte Rate Limiting im Gateway oder im Code passieren?
12. Was sind Per-Endpoint Limits?
13. Was ist ein Rate Limiting Bottleneck?
14. Was ist eine gute Rate Limiting Strategie?
15. Was ist der Vorteil von Retry-After?
Quellen
- https://www.rfc-editor.org/rfc/rfc6585
- https://redis.io/docs/manual/programmability/eval-intro/
- https://www.konghq.com/kong
Buchempfehlungen zur API-Entwicklung
Wenn Du Dich weiter mit Rate Limiting, verteilten Systemen und API-Architektur beschäftigen möchtest, empfehlen wir Dir die folgenden Bücher:
Keine Bücher für Kategorie "api-development" gefunden.