Design Rate Limiter's
1) Warum Rate Limiting
Rate Limiting schützt die Verfügbarkeit und Wirtschaftlichkeit von APIs: Stoppt Floods, „Bursts“ von Retrays, Credential Stuffing, schützt teure Transaktionen (Geldtransaktionen, Berichtsgenerierung), glättet die Belastung abhängiger Systeme (DBs/Provider). Gutes Design gibt Fairness, Vorhersagbarkeit der Latenz und klare SLOs.
Wichtige Ziele
RPS-Stabilität und Schutz des Backends vor Überlastung.
Kontrollierte „Elastizität“ (burst allowance).
Kundendifferenzierung (Per-User/Per-Organisation/Per-Key/Per-IP/Per-Region).
Wertmodell: verschiedene „Preise“ für verschiedene Operationen.
2) Arten von Grenzen
RPS-Limits: Anforderungen pro Sekunde/Minute.
Quoten: Gesamtbudget im Zeitraum (Tag/Monat).
Wettbewerb: gleichzeitige Operationen (Checkout, schwerer Job).
Geschwindigkeit/Band: Byte/sec (Upload/Upload).
Gewichtete Grenzen: „Kosten“ einer Anfrage nach Komplexität (z.B. GraphQL-Komplexität, Batch-Größe).
Adaptiv: werden bei Anomalien härter (verdächtige Aktivität/Fehler 401/403/5xx).
3) Algorithmen und wann sie anzuwenden sind
3. 1 Fixed window counter
Einfach: Zähler pro Intervall (z.B. 100 r/min).
Vorteile: minimale Kosten. Nachteile: „edge bursts“ an den Fensterrändern.
Wann: Adminplatten, geringe Genauigkeit, niedrige Kosten.
3. 2 Sliding window (log / counter)
Log: speichert Zeitstempel der letzten Anfragen, genau, teuer aus dem Speicher.
Counter: der Durchschnitt zweier benachbarter Fenster (Rolling), ein Kompromiss aus Genauigkeit und Preis.
Wann: öffentliche APIs für durchschnittlichen Datenverkehr, Sie brauchen Geschmeidigkeit ohne komplexe Mathematik.
3. 3 Token bucket
Parameter: Geschwindigkeit'r'(Token/sec) und Kapazität'b'(Burst). Jede Anfrage "verbrennt' ein Token.
Vorteile: natürliche Burst Allowance, einfache Implementierung. Nachteile: Es gibt keine strenge Gleichmäßigkeit.
Wann: fast immer für RPS, wenn „Volleys“ innerhalb von'b 'benötigt werden.
3. 4 Leaky bucket (drip)
Eine Warteschlange, aus der mit einer festen Geschwindigkeit „durchsickert“.
Vorteile: gleichmäßiger Ausgangsstrom. Nachteile: mehr Verzögerungen.
Wann: Glättung gegenüber externen „fragilen“ Anbietern.
3. 5 GCRA (Generalized Cell Rate Algorithm)
Theoretisches Ankunftszeitmodell (TAT):- 'TAT _ next = max (TAT_current, jetzt) + 1/r', Anfrage akzeptiert, wenn 'jetzt <= TAT_current + burst/r'.
- Vorteile: streng, genau, wenig Speicher (durch den Schlüssel speichern wir TAT). Nachteile: schwieriger zu verstehen.
Wann: Es braucht strenge Kontrollen und Geschmeidigkeit, verteilte Grenzen.
3. 6 Kompetitive Semaphoren
Zähler der aktiven Operationen; Eintritt - wenn „Tickets“ vorhanden sind; Der Ausweg ist die Befreiung.
Wenn: Langstreckenoperationen, Threads, WebSocket, Downloads.
4) Begrenzungsschlüsselmodell
Schlüssel = Kombination von Attributen:- `client_id`/`api_key`/`user_id`/`org_id`
- „IP/ASN/Geo“ (Grobschutz)
- 'endpoint/method' (heiße Routen)
- „scope/plan/tier“ (Monetarisierung)
- 'idempotency _ key' (Schreibvorgänge)
- Verwenden Sie Hierarchie: zuerst strenge Per-Schlüssel, dann Per-Organisation, dann global.
5) Anforderungsgewicht (Kostenmodell)
Definieren Sie den „Wert“ von „Kosten (q)“:- GraphQL: Komplexität durch Felder × Tiefe.
- REST: Größe der Antwort/Anfrage, Art der Operation (read = 1, write = 3, report = 10).
- Batch: `cost = min(n, cap)`.
- Wir begrenzen Token, nicht „Anfragen“: 'budget - = cost (q)'.
6) Verteilte Implementierung
6. 1 Lagerung
In-Prozess: Ultra-schnell, aber keine allgemeine Grenze (geeignet für lokale „weiche“ Grenzen).
Redis: de facto der Standard. INCR/EXPIRE, Lua-Skripte (Atomarität), ZSET für Schiebefenster, Schlüssel mit TTL.
Envoy/NGINX/Kong/Traefik: integrierte Filter; bequem für den Umfang.
Service Mesh: Lokale Limits auf sidecar + globale Synchronisation.
6. 2 Atomarität und Rennen
Lua in Redis: Check und Inkrement in einem Schritt.
GCRA: Speichern Sie eine einzelne TAT mit CAS/Skript.
Uhrenkonsistenz: NTP, monotone Timer.
Sharding: konsistenter Hash nach Schlüssel; Vermeiden Sie „heiße“ Shards.
6. 3 Geo-Verteilung
Lokale Limits auf regionalen Clustern + Top Global (Coarse).
CRDT/Replikation - Vorsicht (Latenz, doppelter Verbrauch). Regionale Grenzen mit einem Spielraum sind vorzuziehen.
7) Politik und Priorisierung
Pläne: Free/Pro/Enterprise mit verschiedenen'r','b', Quoten.
Prioritäten: „Teure“ Routen bekommen ein kleineres Limit oder mehr Kosten.
Listen: allow-list für Integrationen, deny über ASN/proxy/TOR.
Eskalation: Bei wiederholter Überschreitung senken wir das Limit, führen Proof-of-Work/Captcha/Challenges ein.
8) Beispiele für Config
8. 1 Envoy (HTTP rate limit filter, pseudo)
yaml rate_limit:
domain: public-api descriptors:
- key: api_key rate_limit:
unit: second requests_per_unit: 50 burst: 100
- key: api_key value: payments. write rate_limit:
unit: second requests_per_unit: 5 burst: 10
8. 2 NGINX (lua + Redis, pseudo)
nginx lua_shared_dict limits 10m;
location /api/ {
access_by_lua_block {
local key = ngx. var. arg_apikey.. ":".. ngx. var. request_method.. ":".. ngx. var. uri
-- token bucket in Redis (evalsha)
local allowed, retry_after = ratelimit_allow(key, 50, 100) -- r=50/s, b=100 if not allowed then ngx. header["Retry-After"] = retry_after return ngx. exit(429)
end
}
proxy_pass http://backend;
}
8. 3 Wettbewerbslimits (Pseudocode)
pseudo on_request_start(key):
if redis. incr_with_ttl("sem:" + key, ttl=60) > MAX_CONCURRENCY:
redis. decr("sem:" + key); reject(429)
on_request_finish(key):
redis. decr("sem:" + key)
8. 4 GCRA (Pseudocode)
pseudo params: r tokens/sec, burst b tat = redis. get(key) or now allowed_time = tat - (b / r)
if now < allowed_time: reject(429, retry_after = allowed_time - now)
tat_next = max(tat, now) + 1/r redis. set(key, tat_next, ttl = ceil(b/r) + safety)
9) Integration mit Retrays, Timeouts und Circuit Breaker
Retry-Budget: Begrenzen Sie den Anteil der Retrays auf X% des Hauptverkehrs.
Jitter: Beim Backoff immer Jitter hinzufügen - reduziert synchrone Bursts.
Circuit Breaker: Bei hoher Fehlerquote ('5xx', Timeouts) die Limits senken oder einen Teil der Routen auf „nur lesen“ umstellen.
Hedging: ordentlich; Berücksichtigen Sie die Kosten, um die Ausgaben des Budgets nicht zu verdoppeln.
10) Beobachtbarkeit und Management
Метрики: `rps_allowed`, `rps_blocked`, `429_rate`, `retry_after_avg`, `burst_used`, `quota_remaining`, `active_concurrency`.
Labels: nach Limitschlüssel, Region, Endpoint, Plan.
Entscheidungslogs (Sampled): Fehlerursache, aktuelle Zähler, TTL-Schlüssel.
Dashboards: Heatmaps durch Schlüssel/Endpunkte, „heiße“ Kunden.
Alertas: Wachstum von 429> 2-5% auf kritischen Strecken, häufige „Erschöpfung“ von Quoten, Shard-Ungleichgewicht.
11) Prüfung und Validierung
Vertragsrichtlinientests (Wenn-dann-Tabellen).
Last: Bursts (x10 von r), lange Plateaus, „schmutzige“ Muster (Slow-POST, lange Verbindungen).
Chaos-Verkehr: ungleiche Ströme, Taktdrift, Redis/Mesh-Drop.
A/V-Aktivierung: kanarische Rollout-Limits, Schatten-Lösungen (protokollieren, aber nicht blockieren) vor der Aktivierung.
12) Edge-Fälle und Feinheiten
Clock skew: Verwenden Sie' now () 'aus einer Hand (Server) und nicht aus Client-Headern.
Idempotency-Key: für write - reduziert die Amplifikation bei Retrays.
Batch-Operationen: Begrenzen Sie die Batch-Größe und die Gesamtkosten.
Long-poll/WebSocket: Begrenzen Sie die Anzahl der Kanäle/Abonnements und die Dauer.
Kaltstart: „warmer“ Zählerstart/Vorladen; ansonsten Ausbrüche von falschen 429.
Rechnerisch teure Abfragen: Beschränken Sie sich auf die Ausführung der Geschäftslogik.
TTL-Grenzen: Die TTL der Schlüssel muss das Fenster + die Marge (Sicherheitsmargin) abdecken.
13) Anti-Bottom-Eskalation
Schritte: Warnung → 429 + 'Retry-After' → Challenge (Captcha/Puzzle) → temporärer Block.
Signale: Device-Fingerprint, Cursor/Timing-Verhalten, TOR/Proxy/Hosting.
Policies müssen deterministisch und reproduzierbar für forensics sein.
14) Sicherheit und Compliance
Deny-by-default auf kritischen Routen (write/finance).
Audit: Speichern Sie Limitentscheidungen für regulatorische Fälle und die Analyse von Vorfällen.
PII: Limitschlüssel dürfen keine personenbezogenen Daten in Protokollen offenlegen.
15) Checkliste Prod-Ready
- Limitschlüssel und Cost-Modell sind definiert.
- Algorithmus (Token Bucket/GCRA) und Speicher (Redis/Gateway) ausgewählt.
- Richtlinien für Tier's von Kunden + globale „Sicherungen“.
- Wettbewerbslimits für lange Operationen.
- Retry-Budget, Backoff mit Jitter, Integration mit Circuit Breaker.
- Dashboards/Alerts, gesampelte Entscheidungsprotokolle.
- Canary-on und Shadow-Modus.
- Burst Tests, lange Plateaus, Redis Abstürze, Uhr skew.
- Kundendokumentation: Codes 429, 'Retry-After', Beispiele für exponentiellen Backoff.
16) TL; DR
Verwenden Sie Token Bucket oder GCRA mit Redis/Gateway, entwerfen Sie Limitschlüssel und Anforderungskosten, fügen Sie kompetitive Semaphoren für lange Operationen hinzu, integrieren Sie mit Retry-Budget und Circuit Breaker, beobachten Sie 429 und „Burst Capacity“, rollen Sie Limits über Canary/Shadow aus und stellen Sie sicher, dass Sie Bursts und Speicherausfall testen