8 Punkte von GN⁺ 2026-02-25 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Uber hat in einer Umgebung mit Tausenden von Microservices, die Hunderte Millionen RPCs pro Sekunde verarbeiten, einen Global Rate Limiter (GRL) aufgebaut und damit ein einheitliches Überlastschutzsystem etabliert
  • Der GRL basiert auf einer dreistufigen Feedback-Loop-Architektur aus Client, Aggregator und Controller, die lokale Entscheidungsfindung bei Anfragen ermöglicht und zugleich eine globale Abstimmung innerhalb weniger Sekunden
  • Durch den Wechsel vom anfänglichen Token-Bucket-Ansatz zu einem probabilistischen Drop-Modell wurden Fairness- und Skalierungsprobleme gelöst und die Latenz im Hot Path minimiert
  • Gegenüber Redis-basierten Limitern wurde die P99.5-Latenz um bis zu 90 % verbessert, und auch 15-fache Traffic-Spitzen sowie DDoS-Angriffe konnten ohne Service-Degradierung absorbiert werden
  • Der Rate Limit Configurator (RLC) analysiert historische Traffic-Muster und aktualisiert Limits automatisch, wodurch sich das System von statischen Konfigurationen zu einem selbstanpassenden System weiterentwickelt hat

Probleme bisheriger Rate-Limits

  • In Ubers früherer Microservices-Umgebung implementierte jedes Team sein eigenes Throttling, etwa mit Business-Logik, Custom Middleware oder Redis-basierten Zählern
  • Das führte zu Problemen wie inkonsistenten Konfigurationen, zusätzlicher Redis-bedingter Latenz, nötigen Server-Redeployments bei Limitänderungen sowie schwieriger Incident-Reaktion wegen nicht dokumentierter Limiter
  • Ein erheblicher Teil kleinerer Services lief sogar ganz ohne Rate-Limits, und jeder Limiter meldete Metriken und Fehler anders, sodass keine einheitliche Observability möglich war
  • Die Nutzung von Redis als zentralisiertem Zähler verursachte in einer Multi-Region-Umgebung mit Hunderttausenden Hosts und Hunderten Millionen Requests pro Sekunde untragbare Latenzen und Konsistenzprobleme zwischen Regionen
    • Selbst mit Sharding und Replikation wären Hunderte Redis-Cluster nötig gewesen, was neue Failure Modes eingeführt hätte
  • Auch der Ansatz einer periodischen Synchronisierung von Zählern wurde verworfen: Er reduzierte zwar den Netzwerk-Overhead, brachte aber veraltete Daten und verzögerte Reaktionen auf plötzliche Traffic-Spitzen mit sich
  • Am Ende kam Uber zu dem Schluss, dass nur eine vollständig verteilte Architektur, bei der lokale Proxys auf Basis aggregierter Last entscheiden, gleichzeitig niedrige Latenz und globale Skalierbarkeit erreichen kann

Vision eines einheitlichen Limiters auf Infrastruktur-Ebene

  • Die Lösung bestand darin, Rate-Limiting in Ubers Service Mesh einzubetten, also in die Infrastrukturschicht für RPC-Traffic zwischen Services
  • Durch die Einbettung in diese Schicht können alle Requests unabhängig von Sprache oder Framework des Callers geprüft und bewertet werden, bevor sie ihr Ziel erreichen
  • Ziel war ein einheitlicher Rate-Limiting-Service, mit dem Teams Quoten pro Caller und pro Prozedur ohne Codeänderungen festlegen können
  • Das System musste bei Hunderten Millionen Requests pro Sekunde, Zehntausenden Service-Paaren und Host-Flotten über mehrere geografische Regionen hinweg mit minimal zusätzlicher Latenz skalieren

GRL-Architektur: dreistufiger Feedback-Loop

  • Im Kern des GRL steht eine dreistufige Feedback-Loop-Struktur
    • Rate-Limit-Client (Service-Mesh-Datenebene): trifft lokale Entscheidungen pro Request anhand von Anweisungen vom Aggregator und meldet die Requests pro Sekunde je Host an den zonalen Aggregator
    • Aggregator (pro Zone): sammelt Metriken aller Clients in derselben Zone, berechnet die Nutzung auf Zonenebene und sendet sie an den Controller
    • Controller (pro Region, global): aggregiert die Zonendaten, bestimmt die globale Auslastung und propagiert aktualisierte Drop-Ratio-Anweisungen zurück an Aggregatoren und Clients
  • Diese hierarchische Aggregation ermöglicht gleichzeitig niedrige Latenz im Hot Path (weil Entscheidungen lokal fallen) und globale Abstimmung innerhalb weniger Sekunden
  • Bei Ausfällen der Control Plane arbeiten Clients nach dem Prinzip Fail Open weiter und lassen Traffic passieren, um selbst verursachte Ausfälle zu vermeiden

Entwicklung der Rate-Limiting-Logik

  • Früher Token-Bucket-Ansatz

    • Anfangs wurde in jedem Proxy der Netzwerk-Datenebene ein Token-Bucket-Algorithmus eingesetzt
    • Jeder Proxy verfolgte lokal die Request-Anzahl, füllte Tokens über die Zeit auf und erlaubte oder verweigerte Requests je nach verfügbarer Token-Anzahl
    • Die Token-Auffüllrate wurde aus dem Verhältnis von lokaler Last des Proxys zum globalen Limit berechnet: ratio × limitRPS
    • Um Burst-Traffic abzufangen, wurden ungenutzte Tokens in einem Ringpuffer gespeichert und standardmäßig 10 Sekunden lang aufbewahrt (konfigurierbar bis 20 Sekunden)
    • In Produktion zeigten sich Fairness- und Skalierungsprobleme: Wenn die Zahl der Caller das Limit überschritt, ließ sich die Kapazität nicht fair verteilen, und Burst-Traffic einzelner Hosts führte selbst unterhalb des globalen Limits zu vorzeitigen Drops
  • Einführung von Drop-by-Ratio

    • Überschreitet die aggregierte globale Last das konfigurierte Limit, droppen Clients probabilistisch einen bestimmten Anteil der Requests
    • Beispiel: Liegt die aggregierte RPS eines Callers beim 1,5-Fachen des Limits, werden über alle Instanzen hinweg etwa 33 % gedroppt; Formel: drop_ratio = (actual_rps - limit_rps) / actual_rps
    • Dieses globale Drop-Signal, das von der Control Plane alle paar Sekunden aktualisiert wird, throttelt überschüssigen Traffic gleichmäßig über alle Caller-Instanzen hinweg
    • Besonders wirksam ist das bei großen gatewayartigen Services mit Hunderten bis Tausenden von Caller-Instanzen
  • Übergang zu einem einheitlichen probabilistischen Modell

    • Mit zunehmender Reife des GRL wurde der Token Bucket vollständig abgeschafft und alles auf ein probabilistisches Drop-Modell auf Basis der Control Plane vereinheitlicht
    • Der parallele Betrieb zweier Algorithmen erhöhte nämlich Konfigurationskomplexität und Netzwerk-Overhead
    • Durch die Vereinheitlichung auf ein einziges Modell wurden Konfigurationen vereinfacht, die Bandbreite der Control Plane reduziert und alle Rate-Limit-Entscheidungen unter einem global konsistenten Mechanismus zusammengeführt
    • Der Trade-off: Weil das System auf global aggregierten Daten mit Aktualisierung im Sekundentakt basiert, entsteht eine Durchsetzungsverzögerung von 2 bis 3 Sekunden
      • In der Praxis ist das für die meisten Workloads vernachlässigbar und fällt nur bei sehr kurzen, extremen Bursts ins Gewicht
  • Endgültiges Design: probabilistischer Drop nach Anweisung der Control Plane

    • Im aktuellen GRL erfolgt die Durchsetzung vollständig in der Client-Schicht der Netzwerk-Datenebene
    • Der Ablauf bei eingehenden Requests:
      • Abgleich des Requests mit einem konfigurierten Bucket (definiert nach Caller, Prozedur oder beidem)
      • Falls für diesen Bucket eine aktive Drop-Ratio-Anweisung existiert, erfolgt ein probabilistischer Drop gemäß dieser Ratio
      • Wenn keine Drop-Anweisung vorliegt, wird der Request normal weitergeleitet
    • Der Hot Path ist extrem leichtgewichtig: keine lokale Token-Berechnung, keine Kommunikation mit der Control Plane pro Request, nur einfaches probabilistisches Sampling im Prozess
    • Aggregatoren und Controller führen außerhalb der Datenebene jede Sekunde komplexe Berechnungen aus, etwa das Aggregieren von Request-Zahlen, den Vergleich mit Schwellenwerten und die Berechnung neuer Drop-Ratios
    • Dieses Design skaliert auf Hunderte Millionen Requests pro Sekunde und hält dabei eine globale Durchsetzungsgenauigkeit innerhalb weniger Sekunden aufrecht

Konfiguration von Limits

  • Service-Owner definieren Rate-Limit-Buckets in einer Konfigurationsdatei
    • Scope: global, pro Region oder pro Zone
    • Matching-Regeln: Caller-Name, Prozedur oder beides
    • Verhalten: deny (Durchsetzung) oder allow (Shadow-Modus für Tests)
  • Die Anwendung erfolgt für den Zielservice transparent ohne Codeänderungen

Operative Ergebnisse

  • Niedrigere Latenz und Wegfall von Overhead

    • Vor dem GRL nutzten viele Services Redis-basierte Limiter, die für jeden Request einen Netzwerk-Roundtrip benötigten
    • Durch die Umstellung auf lokale Auswertung in der Service-Mesh-Datenebene entfiel dieser zusätzliche Hop, und die Latenz sank deutlich
    • Die P50-Latenz wurde um etwa 1 ms reduziert, P90 um mehrere zehn Millisekunden, und bei P99.5 sank sie von mehreren hundert Millisekunden auf einige Dutzend Millisekunden – eine Verbesserung von bis zu 90 %
  • Vereinfachter Betrieb und bessere Ressourceneffizienz

    • Die Zentralisierung des Rate-Limitings in der Service-Mesh-Datenebene vereinfachte die Infrastruktur
    • Es sind keine separaten Datenspeicher oder Caching-Layer mehr nötig, um Quoten durchzusetzen
    • Durch die Abschaltung zahlreicher zuvor ausschließlich fürs Rate-Limiting genutzter Redis-Instanzen wurde eine spürbare Compute-Effizienz erzielt
  • Höhere Stabilität und bessere Incident-Reaktion

    • Seit dem Rollout verhindert der GRL wiederholt Überlastung bei Spikes, Failovern und Retry Storms
    • Indem überschüssiger Traffic im Service Mesh probabilistisch abgeschält wird, bleiben konsistente Antwortzeiten auch bei abrupt steigender Eingangslast erhalten
    • Ein kritischer Service verkraftete einen 15-fachen Traffic-Anstieg von 22K auf 367K RPS ohne Degradierung
    • DDoS-Angriffe wurden absorbiert, bevor sie interne Systeme erreichten
    • Bei Incident-Reaktionen kann das Production-Engineering-Team mit GRL gezielte Rate-Limits auf bestimmte High-Traffic-Caller oder Prozeduren anwenden; Updates der Control Plane werden sekündlich propagiert, sodass sich Überlastungen innerhalb weniger Sekunden eindämmen lassen
    • Bestimmte Traffic-Muster lassen sich schnell und sicher throttlen, ohne Services neu deployen zu müssen
    • Gesamtskala: rund 80 Millionen Requests pro Sekunde, mit dynamischer Quotendurchsetzung in mehr als 1.100 Services

Automatisierung von Rate-Limits: Rate Limit Configurator (RLC)

  • Grenzen manueller Konfiguration

    • Obwohl der GRL die Durchsetzung vereinheitlicht hat, erfordert das Setzen von Limits weiterhin manuelle Arbeit
    • Service-Owner definieren Quoten pro Caller und Prozedur in YAML-Dateien und passen sie bei Änderungen der Traffic-Muster an
    • In einer Umgebung mit Hunderten sich ständig weiterentwickelnden Microservices veralten statische Konfigurationen schnell
      • Sind Limits zu streng, kommt es selbst bei normalen Traffic-Spitzen zu Throttling
      • Sind sie zu locker, liegen sie über der realen Kapazität und bieten kaum Schutz
      • Änderungen hängen von Dashboard-Analysen und manueller Feinabstimmung ab
  • Funktionsweise des RLC

    • Der RLC (Rate Limit Configurator) hält die GRL-Konfiguration automatisch aktuell
    • Nach festem Zeitplan oder unmittelbar bei Konfigurationsänderungen durchläuft er den nächsten Zyklus:
      • Sammeln von Metriken der vergangenen Wochen aus Ubers Observability-Plattform
      • Berechnung sicherer Limits pro Caller und Prozedur anhand historischer Peaks und zusätzlicher Puffer
      • Schreiben der aktualisierten Konfiguration in ein gemeinsames Konfigurations-Repository
      • Pushen neuer Limits an den GRL über die bestehende Control Plane
    • Durch diesen Closed-Loop-Prozess entwickeln sich Limits mit dem realen Traffic weiter, bei minimalem manuellem Eingriff
  • Skalierbares Design

    • Der RLC wurde von Beginn an für die Unterstützung mehrerer Strategien zur Berechnung von Rate-Limits ausgelegt
    • Die Standardrichtlinie basiert auf historischen RPS-Daten, doch neue Policy-Typen lassen sich modular ergänzen
    • Services für Mapping- und Standortdaten nutzen etwa prognostische Modelle, die Traffic-Vorhersagen und geplante Kapazität berücksichtigen, statt nur historische Trends
    • Unterstützt wird auch die Zuweisung fester Quoten auf Basis vorab vereinbarter vertraglicher oder operativer Absprachen
    • Über modulare Schnittstellen kann je nach Service-Domäne die passende Berechnungslogik gewählt werden: nahezu Echtzeit-Traffic-Muster, Prognosen oder statische Quoten
  • Shadow-Modus und Validierung

    • Aus Sicherheitsgründen können Limits im Shadow-Modus erzeugt und überwacht werden, ohne sie aktiv durchzusetzen
    • Service-Owner beobachten dann zunächst das Verhalten der Rate-Limits in Produktion und aktivieren sie erst danach
    • Eigene Dashboards und Alerts visualisieren beobachteten Traffic und virtuelle Drops und schaffen so Vertrauen vor dem Rollout
  • Wirkung der Automatisierung

    • Tausende von Rate-Limit-Regeln werden automatisch aktualisiert, ohne manuelle Bearbeitung
    • Auf Basis derselben Formeln und Datenquellen entstehen konsistente Richtlinien über alle Services hinweg
    • Dank verschiedener Policy-Typen können Teams die für ihren Workload passende Berechnungslogik auswählen und erweitern
    • Der Shadow-Modus sorgt vor der Durchsetzung für abgesicherte Genauigkeit

Ausblick

  • Auch nach Einführung des RLC arbeitet Uber weiter an größerer Puffer-Feinabstimmung, an regionenspezifischen Rate-Limits zur Verringerung des Blast Radius von Konfigurationsänderungen und an höherer Update-Frequenz, um stärker auf Live-Traffic zu reagieren
  • Ubers Throttler-Layer sorgt näher an der Anwendung zusätzlich für Überlastschutz
  • Der GRL ist heute ein zentraler Bestandteil von Ubers mehrschichtigem Stabilitäts-Stack und sichert die Stabilität und Fairness der Plattform selbst unter extremer Last

Noch keine Kommentare.

Noch keine Kommentare.