8 points par GN⁺ 2026-02-25 | Aucun commentaire pour le moment. | Partager sur WhatsApp
  • Uber a mis en place un Global Rate Limiter (GRL) dans un environnement de milliers de microservices traitant des centaines de millions de RPC par seconde, afin d’établir un mécanisme unifié de protection contre la surcharge
  • Le GRL repose sur une architecture en boucle de rétroaction à 3 niveaux composée de clients, d’agrégateurs et de contrôleurs, permettant de décider localement du sort des requêtes tout en assurant une coordination globale en quelques secondes
  • Uber a abandonné l’approche initiale par token bucket au profit d’un modèle de drop probabiliste, afin de résoudre les problèmes d’équité et de scalabilité tout en minimisant la latence sur le hot path
  • Par rapport à un limiteur fondé sur Redis, la latence P99.5 a été améliorée jusqu’à 90 %, et le système a absorbé sans dégradation des pointes de trafic de 15x ainsi que des attaques DDoS
  • Le Rate Limit Configurator (RLC) analyse les schémas de trafic passés pour mettre automatiquement à jour les quotas, faisant évoluer le système d’une configuration statique vers un mécanisme auto-ajusté

Les problèmes des anciens mécanismes de limitation

  • Dans l’environnement initial de microservices d’Uber, chaque équipe implémentait son propre throttling via logique métier, middleware personnalisé ou compteurs basés sur Redis
  • Cela a entraîné des problèmes de configurations incohérentes, de latence additionnelle liée à Redis, de nécessité de redéployer les serveurs lors des changements de quotas, ainsi que des difficultés de réponse aux incidents à cause de limiteurs non documentés
  • Une part importante des petits services fonctionnait même sans aucun rate limiting, et chaque limiteur exposait métriques et erreurs différemment, empêchant toute observabilité unifiée
  • L’usage de Redis comme compteur centralisé entraînait, à l’échelle de centaines de milliers d’hôtes, de centaines de millions de requêtes par seconde et de multiples régions, une latence inacceptable ainsi que des problèmes de cohérence inter-régions
    • Même avec sharding et réplication, cela aurait nécessité des centaines de clusters Redis, tout en ajoutant de nouveaux modes de panne
  • La synchronisation périodique des compteurs réduisait bien la surcharge réseau, mais a été écartée à cause du manque de fraîcheur des données et du retard de réaction face aux pics brutaux de trafic
  • Uber en est finalement arrivé à la conclusion que seule une architecture entièrement distribuée, dans laquelle des proxys locaux décident sur la base d’une charge agrégée, pouvait atteindre à la fois une faible latence et une scalabilité globale

Vision d’un limiteur unifié au niveau infrastructure

  • La solution consistait à intégrer le rate limiting dans le service mesh d’Uber, la couche d’infrastructure gérant le trafic RPC entre services
  • En embarquant le limiteur dans cette couche, il devient possible d’inspecter et d’évaluer toutes les requêtes quel que soit le langage ou le framework de l’appelant, avant qu’elles n’atteignent la destination
  • Objectif : fournir un service unifié de rate limiting permettant aux équipes de définir des quotas par appelant et par procédure sans modifier le code
  • Le système devait passer à l’échelle de centaines de millions de requêtes par seconde, de dizaines de milliers de paires de services et de flottes d’hôtes réparties sur plusieurs régions géographiques, avec un surcoût de latence minimal

Architecture du GRL : une boucle de rétroaction à 3 niveaux

  • Au cœur du GRL se trouve une structure en boucle de rétroaction à 3 niveaux
    • Client de rate limiting (data plane du service mesh) : prend localement une décision pour chaque requête selon les consignes reçues des agrégateurs, et remonte aux agrégateurs au niveau de la zone le nombre de requêtes par seconde observé sur chaque hôte
    • Agrégateur (par zone) : collecte les métriques de tous les clients d’une même zone, calcule l’usage au niveau zone et l’envoie au contrôleur
    • Contrôleur (par région, global) : agrège les données des zones, évalue l’utilisation globale et renvoie vers les agrégateurs et clients des consignes de taux de drop mises à jour
  • Cette agrégation hiérarchique permet de conserver une faible latence sur le hot path (décision locale) tout en assurant une coordination globale en quelques secondes
  • En cas de panne du control plane, les clients fonctionnent en fail-open, laissant passer le trafic afin d’éviter une panne auto-infligée

Évolution de la logique de rate limiting

  • Approche initiale par token bucket

    • Au départ, Uber appliquait un algorithme de token bucket dans chaque proxy du data plane réseau
    • Chaque proxy suivait localement le volume de requêtes et reconstituait des tokens au fil du temps, autorisant ou refusant les requêtes selon le nombre de tokens disponibles
    • Le taux de reconstitution était calculé à partir du ratio entre la charge locale du proxy et le quota global : ratio × limitRPS
    • Pour absorber les bursts, les tokens inutilisés étaient stockés dans un buffer circulaire, conservés par défaut 10 secondes (jusqu’à 20 secondes par configuration)
    • En production, des problèmes d’équité et de scalabilité sont apparus : quand le nombre d’appelants dépassait le quota, il devenait impossible de répartir la capacité équitablement, et des bursts sur certains hôtes provoquaient des drops prématurés même sous le quota global
  • Introduction de Drop-by-Ratio

    • Quand la charge globale agrégée dépassait le quota configuré, les clients dropaient probabilistiquement une fraction des requêtes
    • Exemple : si le RPS agrégé d’un appelant atteignait 1,5 fois la limite, alors environ 33 % des requêtes étaient dropées sur toutes les instances, selon la formule : drop_ratio = (actual_rps - limit_rps) / actual_rps
    • Grâce à ce signal de drop global mis à jour toutes les quelques secondes par le control plane, le trafic excédentaire était throttlé uniformément sur toutes les instances de l’appelant
    • L’approche s’est révélée particulièrement efficace pour les grands services de type gateway comptant des centaines à des milliers d’instances appelantes
  • Passage à un modèle probabiliste unifié

    • À mesure que le GRL gagnait en maturité, Uber a totalement abandonné le token bucket pour un modèle unifié de drop probabiliste piloté par le control plane
    • Le maintien simultané de deux algorithmes augmentait en effet la complexité de configuration et la surcharge réseau
    • Cette unification a permis de simplifier la configuration, de réduire la bande passante du control plane et de rassembler toutes les décisions de rate limiting sous un mécanisme global cohérent
    • Compromis : le système dépend de données agrégées globales mises à jour chaque seconde, ce qui introduit un délai d’application de 2 à 3 secondes
      • En pratique, ce délai est négligeable pour la plupart des workloads, et n’a d’impact que sur des bursts extrêmement courts et violents
  • Design final : drop probabiliste piloté par le control plane

    • Dans le GRL actuel, l’application se fait entièrement au niveau de la couche cliente du data plane réseau
    • Flux de traitement à l’arrivée d’une requête :
      • Association de la requête à un bucket configuré (défini par l’appelant, la procédure, ou les deux)
      • Si ce bucket a une consigne active de taux de drop, application d’un drop probabiliste selon ce taux
      • En l’absence de consigne de drop, la requête est transmise normalement
    • Le hot path est extrêmement léger : aucun calcul local de tokens ni communication avec le control plane pour chaque requête, seulement un simple échantillonnage probabiliste en mémoire de processus
    • Les agrégateurs et contrôleurs effectuent hors du forwarding plane les calculs complexes (agrégation du nombre de requêtes, comparaison aux seuils, calcul des nouveaux taux de drop) chaque seconde
    • Ce design permet de passer à l’échelle de centaines de millions de requêtes par seconde tout en conservant une précision d’application globale en quelques secondes

Configuration des quotas

  • Les propriétaires de services définissent les buckets de rate limiting dans un fichier de configuration
    • Scope : global, par région, par zone
    • Règles de matching : nom de l’appelant, procédure, ou les deux
    • Comportement : deny (application réelle) ou allow (shadow mode pour les tests)
  • Le mécanisme s’applique de manière transparente au service de destination, sans modification de code

Résultats opérationnels

  • Réduction de la latence et suppression du surcoût

    • Avant le GRL, de nombreux services utilisaient un limiteur basé sur Redis nécessitant un aller-retour réseau pour chaque requête
    • Le passage à une évaluation locale dans le data plane du service mesh a supprimé ce saut supplémentaire et réduit fortement la latence
    • La latence P50 a baissé d’environ 1 ms, la P90 de plusieurs dizaines de ms, et la P99.5 est passée de plusieurs centaines de ms à quelques dizaines de ms, soit jusqu’à 90 % d’amélioration
  • Simplification opérationnelle et efficacité des ressources

    • La centralisation du rate limiting dans le data plane du service mesh a simplifié l’infrastructure
    • Plus besoin de datastore dédié ni de couche de cache pour appliquer les quotas
    • La désactivation d’un grand nombre d’instances Redis auparavant dédiées au rate limiting a apporté un gain significatif en efficacité de calcul
  • Amélioration de la stabilité et réponse aux incidents

    • Depuis son déploiement, le GRL a empêché à plusieurs reprises des surcharges liées à des pics, des failovers et des tempêtes de retries
    • En shedant probabilistiquement le trafic excédentaire dans le service mesh, le système a maintenu des temps de réponse stables même lors d’augmentations soudaines de charge entrante
    • Un service critique a absorbé sans dégradation une hausse de trafic de 15x, passant de 22K à 367K RPS
    • Des attaques DDoS ont été absorbées avant même d’atteindre les systèmes internes
    • Lors de la réponse à un incident, l’équipe de production engineering peut utiliser le GRL pour appliquer un rate limiting ciblé à certains appelants ou procédures à fort trafic, les mises à jour du control plane se propageant chaque seconde pour réagir en quelques secondes
    • Il devient ainsi possible de throttler rapidement et en toute sécurité certains patterns de trafic, sans redéployer les services
    • À l’échelle globale : environ 80 millions de requêtes par seconde, avec des quotas dynamiques appliqués à plus de 1 100 services

Automatisation du rate limiting : Rate Limit Configurator (RLC)

  • Les limites de la configuration manuelle

    • Même si le GRL a unifié l’application, la définition des quotas restait un travail manuel
    • Les propriétaires de services devaient définir en YAML des quotas par appelant et par procédure, puis les ajuster à chaque évolution du trafic
    • Dans un environnement de centaines de microservices en évolution continue, les configurations statiques devenaient vite obsolètes
      • Trop strictes, elles provoquaient du throttling même lors de pics légitimes
      • Trop lâches, elles fixaient des quotas trop élevés par rapport à la capacité réelle et réduisaient fortement l’effet protecteur
      • Les changements dépendaient de l’analyse de dashboards et d’un tuning manuel
  • Fonctionnement du RLC

    • Le RLC (Rate Limit Configurator) maintient automatiquement à jour la configuration du GRL
    • Selon un planning fixe ou immédiatement après un changement de configuration, il exécute le cycle suivant :
      • Collecte des métriques des semaines précédentes via la plateforme d’observabilité d’Uber
      • Calcul de quotas sûrs par appelant et par procédure à partir des pics historiques et de marges de sécurité
      • Écriture de la configuration mise à jour dans un dépôt de configuration partagé
      • Push des nouveaux quotas vers le GRL via le control plane existant
    • Ce processus en boucle fermée permet aux quotas d’évoluer avec le trafic réel, en minimisant l’intervention manuelle
  • Un design extensible

    • Le RLC a été conçu dès le départ pour prendre en charge plusieurs stratégies de calcul de rate limiting
    • La politique par défaut repose sur l’historique des données RPS, mais de nouveaux types de politiques peuvent être ajoutés de manière modulaire
    • Des services comme ceux de cartographie ou de données de localisation utilisent des modèles prédictifs intégrant prévisions de trafic et capacité planifiée, afin d’anticiper la charge future plutôt que de s’appuyer sur les seules tendances passées
    • Le système prend aussi en charge l’allocation de quotas fixes définis par des accords contractuels ou opérationnels préétablis
    • Grâce à cette interface modulaire, chaque domaine de service peut choisir la logique de calcul la plus adaptée entre patterns de trafic quasi temps réel, prévisions ou quotas statiques
  • Shadow mode et validation

    • Pour des raisons de sécurité, il est possible de générer et de superviser des quotas en shadow mode sans les appliquer
    • Les propriétaires de services peuvent observer en production le comportement du rate limiting avant de l’activer
    • Des dashboards dédiés et des alertes visualisent le trafic observé et les drops virtuels, afin d’instaurer la confiance avant le rollout
  • Effets de l’automatisation

    • Des milliers de règles de rate limiting sont mises à jour automatiquement sans édition manuelle
    • Une politique cohérente est générée sur l’ensemble des services à partir des mêmes formules et sources de données
    • Grâce aux différents types de politiques, les équipes peuvent choisir et étendre la logique de calcul la mieux adaptée à leur workload
    • Le shadow mode permet de garantir la justesse avant mise en production

Orientations futures

  • Après l’introduction du RLC, Uber continue d’étendre le tuning des buffers, d’introduire du rate limiting par région pour réduire l’impact des changements de configuration, et d’augmenter la fréquence des mises à jour afin d’améliorer la réactivité au trafic live
  • La couche de throttling d’Uber apporte aussi une protection supplémentaire contre la surcharge, plus proche de l’application
  • Aujourd’hui, le GRL est un composant central de la pile de stabilité multicouche d’Uber, garantissant la stabilité et l’équité de la plateforme même sous charge extrême

Aucun commentaire pour le moment.

Aucun commentaire pour le moment.