Maison >développement back-end >Golang >ThrottleX : passer à un million de requêtes par seconde sans transpirer

ThrottleX : passer à un million de requêtes par seconde sans transpirer

Patricia Arquette
Patricia Arquetteoriginal
2024-10-22 14:59:03600parcourir

Faites défiler vers le bas si vous voulez le tester vous-même !!

Présentation :

Gérer des millions de requêtes par seconde ? Est-ce même possible ? ?

Quand on parle de systèmes distribués à grande échelle, les choses peuvent devenir… compliquées. Vous connaissez le principe : la limitation du débit est essentielle pour prévenir les abus, mais elle devient souvent un goulot d'étranglement. Et si je vous disais que nous avons conçu un système capable de gérer 1 million de requêtes par seconde sans accroc ? Découvrez ThrottleX, ma bibliothèque open source distribuée à limitation de débit écrite en Go.

Dans cet article, je vais lever le rideau et vous montrer exactement comment nous avons atteint cette échelle époustouflante. Je vais vous expliquer les optimisations avancées, le modèle de concurrence Go qui a rendu tout cela possible, et même quelques goulots d'étranglement surprises que nous avons rencontrés en cours de route. Mais ce n’est pas seulement de la théorie – je vais partager les véritables repères que nous avons atteints. Attachez votre ceinture car nous sommes sur le point de dépasser certaines limites ! ?


Section 1 : Le défi – Pourquoi l’échelle est importante

La limitation du taux de mise à l'échelle est l'une de ces choses qui semblent simples jusqu'à ce que vous essayiez de le faire à une échelle extrême. La plupart des systèmes fonctionnent avec quelques centaines ou milliers de requêtes par seconde. Mais lorsque vous recevez des millions de demandes, les choses s'effondrent rapidement :

  • Problèmes de gestion de la mémoire ?
  • Goutts d'étranglement du réseau ?
  • Cauchemars de concurrence ?

L'astuce ne consiste pas seulement à limiter le débit : elle le fait efficacement sur plusieurs nœuds, garantissant que chaque requête est traitée à la vitesse de l'éclair sans consommer toutes les ressources disponibles. C'est là que ThrottleX entre en jeu. Conçu pour la vitesse, conçu pour l'évolutivité, il utilise un mélange d'algorithmes de limitation de débit et d'optimisations en temps réel pour garder une longueur d'avance.

Mais pourquoi est-ce important ? Examinons quelques scénarios du monde réel :

  • API sous forte charge : votre API est l'épine dorsale de votre application, et lorsque le trafic augmente (bonjour, moment viral ! ?), vous avez besoin d'un moyen de gérer cet afflux sans tout supprimer.
  • Microservices distribués : lorsque les services dépendent d'API externes, garantir des performances cohérentes sur des millions de requêtes maintient l'ensemble du système stable.
  • Applications à l'échelle du cloud : avec l'infrastructure cloud, vous devez optimiser les coûts tout en gérant des charges de travail imprévisibles. C'est là qu'une limitation efficace des tarifs vous fait gagner du temps (et votre facture cloud ?).

ThrottleX n'est pas n'importe quel limiteur de débit : il est conçu pour des conditions extrêmes, et je vais vous montrer exactement comment nous l'avons poussé jusqu'à ses limites.


Section 2 : Décomposer – L'architecture de ThrottleX

Au cœur de ThrottleX se trouve une combinaison d'algorithmes intelligents de limitation de débit et d'un modèle de concurrence hautement optimisé. Mais il ne s’agit pas seulement des algorithmes : il s’agit également de la manière dont ils sont implémentés et de la manière dont nous les rendons évolutifs dans des environnements distribués. Examinons l'architecture de base qui fait que tout fonctionne.

1. Les algorithmes derrière la magie

En matière de limitation de débit, vous avez probablement entendu parler des classiques :

  • Token Bucket : permet des rafales de trafic mais recharge les jetons à un rythme constant.
  • Fenêtre coulissante : fluidifie le trafic au fil du temps, en comptant les demandes par intervalles de temps glissants.
  • Seau qui fuit : pensez-y comme à un seau avec un trou – les demandes « fuient » à un rythme constant.

ThrottleX ne réinvente pas la roue, mais nous avons pris ces algorithmes éprouvés et les avons rendus plus intelligents. Voici comment :

  • Limitation dynamique des tarifs : Nous avons mis en place un système flexible où les limites de tarifs peuvent s'adapter en temps réel en fonction des conditions de circulation. Si le trafic augmente soudainement, ThrottleX peut gérer la charge sans limitation excessive, permettant ainsi un débit optimal.
  • Gestion des accès simultanés : la limitation du débit peut être particulièrement délicate lors du traitement des requêtes simultanées. Nous avons utilisé des verrous mutex pour garantir qu'aucune condition de concurrence ne se produise, tout en permettant une concurrence maximale.

2. Modèle Go Concurrency – La sauce secrète

L'une des raisons pour lesquelles ThrottleX est intégré à Go est ses goroutines et ses canaux, qui nous offrent une concurrence insensée avec une surcharge minimale. Voici pourquoi le modèle de concurrence de Go a changé la donne pour nous :

  • Les goroutines sont bon marché : contrairement aux threads traditionnels, les goroutines ont une minuscule empreinte mémoire. Cela signifie que nous pouvons en générer des millions sans écraser les ressources du système.
  • Traitement asynchrone : En traitant les requêtes de manière asynchrone, nous évitons de bloquer les opérations. Ceci est essentiel pour que ThrottleX reste réactif en cas de trafic élevé. Chaque demande est traitée dans sa propre goroutine, avec des canaux facilitant la communication entre eux pour une coordination fluide.

En termes simples, c'est comme avoir une chaîne de montage super efficace : chaque travailleur (goroutine) fait son travail sans attendre que quelqu'un d'autre finisse.

3. Optimisation du stockage distribué avec Redis

Un limiteur de débit distribué a besoin d'un état partagé, c'est là que Redis entre en jeu. Mais nous ne pouvions pas simplement brancher Redis et mettre un terme à cela : nous devions l'optimiser :

  • Politiques d'expiration des clés : Redis stocke les paires clé-valeur pour chaque client à débit limité, mais il était crucial de définir des délais d'expiration efficaces pour ces clés. Si les clés n’expirent pas assez vite, vous gaspillez de la mémoire ; trop vite et vous perdez la trace des limites de débit. Nous avons affiné le TTL (durée de vie) pour nous assurer d'atteindre le juste équilibre entre l'efficacité et la précision de la mémoire.
  • Minimiser la latence Redis : Redis est déjà rapide, mais sous une charge importante, des pics de latence peuvent encore se produire. Nous avons optimisé en modifiant les paramètres de pipelining et de réplication. Cela nous permet de transmettre plus de requêtes par seconde tout en gardant la latence de la base de données sous contrôle.

4. Requêtes par lots pour des gains de performances

Une autre astuce que nous avons utilisée pour augmenter notre capacité consiste à regrouper les requêtes. Au lieu de traiter chaque demande individuellement, ThrottleX les regroupe en arrière-plan. Cela réduit le nombre d'opérations qui touchent le backend Redis, ce qui entraîne moins d'allers-retours et un débit plus rapide.

Pensez-y comme si vous envoyiez des colis par la poste. Au lieu de vous rendre au bureau de poste pour chaque lettre, vous attendez d'avoir une pile et de les envoyer toutes en même temps, ce qui vous fait gagner du temps et de l'énergie.


Cette architecture, construite sur la puissance de Go et des configurations Redis optimisées, a donné à ThrottleX la capacité de gérer efficacement des charges de trafic massives. Et le meilleur ? Tout est conçu pour évoluer avec un minimum de modifications, donc que vous traitiez des milliers ou des millions de demandes, ThrottleX a ce qu'il vous faut.


Section 3 : Le secret du million de demandes – Optimisations clés

Alors, comment avons-nous réellement poussé ThrottleX pour gérer un million de requêtes par seconde sans faire planter le système ni faire exploser l'infrastructure ? Cela se résumait à une série d’optimisations soigneusement conçues, à la fois dans les algorithmes de limitation de débit et dans l’architecture système sous-jacente. Voici la sauce secrète :

1. Requêtes par lots pour un débit élevé

L'un des plus grands changements a été le regroupement des requêtes. Plutôt que de traiter chaque demande individuellement, nous les avons regroupées en lots. Cela a considérablement réduit le nombre d'opérations sur notre backend (Redis), entraînant moins d'allers-retours, une latence plus faible et un débit plus rapide.

En d’autres termes, c’est comme traiter une centaine de demandes dans le temps qu’il faudrait normalement pour en traiter dix. Cette optimisation à elle seule a permis une augmentation de 50 % du débit dans nos benchmarks.

2. Disjoncteurs pour éviter les surcharges

Lorsque vous gérez un trafic à cette échelle, les choses peuvent mal tourner. Pour empêcher ThrottleX d'être submergé lors des pics de trafic, nous avons mis en place un modèle de disjoncteur.

Voici comment cela fonctionne :

  • Si un service en aval (comme Redis ou un service client) commence à prendre du retard ou tombe en panne, le disjoncteur se déclenche, interrompant immédiatement les requêtes adressées à ce service.
  • Cela évite une surcharge, permettant au système de récupérer correctement sans planter.
  • Une fois le problème résolu, le disjoncteur se « réinitialise » et la circulation circule à nouveau normalement.

Cette conception permet de maintenir une haute disponibilité, même en cas de charge intense ou de pannes temporaires du système. Sans cela, ThrottleX s'effondrerait lorsque la réplication Redis prendrait du retard ou lorsque le trafic augmenterait de manière inattendue.

3. Efficacité de la mémoire – Optimisation des Goroutines et du pooling

La concurrence est une arme à double tranchant. Bien que les goroutines de Go soient légères, elles nécessitent néanmoins une gestion de la mémoire. Au fur et à mesure de notre évolution, le processus de collecte des déchets (GC) est devenu un goulot d'étranglement, altérant nos performances, en particulier sous de lourdes charges.

Notre solution ? Mutualisation des ressources :

  • Nous avons réutilisé les goroutines autant que possible, réduisant ainsi l'empreinte mémoire et minimisant les frais généraux du GC.
  • Nous avons également mis en œuvre des pools de mémoire personnalisés pour les structures de données fréquemment utilisées afin d'éviter une allocation et une désallocation constantes de mémoire.

Le résultat ? Une réduction de 30 % de l'utilisation de la mémoire et des performances beaucoup plus fluides lors des rafales de trafic.

4. Optimisation du pipeline Redis

Pour garantir que Redis puisse répondre à la charge massive de requêtes, nous avons affiné la fonctionnalité pipelining. Au lieu d'envoyer chaque commande à Redis une par une (ce qui introduit une latence), nous avons regroupé plusieurs commandes en une seule requête unique. Cela a permis à Redis de traiter des lots de commandes en parallèle, réduisant ainsi considérablement les temps de réponse.

La magie du pipeline Redis réside dans la façon dont il minimise les E/S réseau et augmente le débit. Grâce à cette optimisation, Redis a pu traiter des millions de requêtes par seconde avec une latence inférieure à la milliseconde.

5. Limitation de débit adaptative

Nous avons poussé la limitation de débit à un niveau supérieur en la rendant adaptative. Au lieu d'utiliser un tarif fixe à tous les niveaux, ThrottleX peut ajuster dynamiquement la limite de débit en fonction des conditions de circulation en temps réel.

Imaginez ceci : lors d'un trafic normal, le système permet un flux constant de demandes. Mais lors d'un pic soudain (par exemple, une vente flash sur un site de commerce électronique ou un moment d'application virale), ThrottleX assouplira temporairement les limites, permettant à davantage de trafic de passer sans limitation trop agressive. Une fois le pic atténué, il ramène automatiquement le taux à la baisse.

Cette approche adaptative garantit que les utilisateurs légitimes ne sont pas limités lors des pics de trafic, tout en protégeant votre backend contre les abus.

6. Métriques et surveillance en temps réel

Nous voulions aller au-delà de la limitation des tarifs : nous voulions une visibilité sur ce qui se passait à grande échelle. Pour ce faire, nous avons intégré la surveillance en temps réel avec des outils comme Prometheus et Grafana. Cela nous a permis de suivre les indicateurs clés :

  • Débit des requêtes (RPS – Requêtes par seconde)
  • Taux d'erreur
  • Latence Redis
  • Utilisation de Goroutine

Ces informations nous ont permis de détecter rapidement les goulots d'étranglement en matière de performances et d'affiner le système avant qu'ils ne deviennent des problèmes. Grâce à des tableaux de bord affichant le trafic en temps réel et l'état du système, nous avons pu surveiller les performances de ThrottleX même pendant les charges de pointe.


Ces optimisations, fonctionnant ensemble, sont ce qui a permis de gérer 1 million de requêtes par seconde. Chaque ajustement, du traitement par lots et du pipeline à l'optimisation de la mémoire et à la limitation adaptative du débit, a poussé ThrottleX plus loin dans le territoire de l'hyperscale. ?


Section 4 : Benchmarks réels – Prouvez-le ou perdez-le

Soyons réalistes : il est facile de parler d’optimisation, mais la preuve est toujours dans les chiffres. Après des séries de tests de résistance, d'analyse comparative et de réglage fin, voici les mesures réelles que nous avons obtenues avec ThrottleX.

Configuration du benchmark

Nous avons exécuté les tests en utilisant la configuration suivante :

  • Environnement : une configuration de système distribué avec 5 nœuds, chacun fonctionnant sur un processeur à 4 cœurs avec 16 Go de RAM.
  • Backend : Redis pour l'état partagé entre les nœuds, affiné avec le pipeline et l'expiration optimisée des clés.
  • Charge de trafic : nous avons simulé jusqu'à 1 million de requêtes par seconde avec des modèles de trafic réguliers et en rafale.
  • Outils : Prometheus pour la surveillance et Grafana pour la visualisation en temps réel des métriques.

Maintenant, passons à la partie amusante. Voici les résultats :

1. Débit – 1 million de requêtes par seconde

  • Requêtes par seconde (RPS) : nous avons traité systématiquement 1 million de RPS sur plusieurs nœuds.
  • Pic de trafic : lors des scénarios de rafale, ThrottleX a géré des pics de trafic allant jusqu'à 1,2 million de RPS sans aucune baisse significative des performances.

ThrottleX a géré cette charge tout en maintenant faible latence et une consommation de ressources minimale à tous les niveaux.

2. Latence – Temps de réponse inférieurs à la milliseconde

La latence est toujours une préoccupation lorsqu'il s'agit de systèmes distribués, en particulier à cette échelle. Cependant, ThrottleX a toujours fourni des temps de réponse inférieurs à la milliseconde, même dans des conditions de trafic extrêmes.

  • Latence Redis moyenne : 0,7 ms
  • Latence moyenne des requêtes : 0,8 ms

Grâce à des optimisations telles que le pipeline Redis et les requêtes par lots, nous avons minimisé les allers-retours vers la base de données, maintenant la latence bien inférieure à 1 ms.

3. Efficacité de la mémoire – 30 % d'utilisation de la mémoire en moins

En optimisant les goroutines et le le pooling de mémoire, nous avons obtenu une réduction de 30 % de l'utilisation de la mémoire par rapport aux limiteurs de débit traditionnels. Voici une répartition :

  • Goroutine Pooling : réduction de la surcharge liée à la génération de millions de requêtes simultanées.
  • Pools de mémoire personnalisés : réduction significative du nombre d'allocations lors des rafales de trafic, conduisant à des performances plus stables et à des pauses de récupération de place moins fréquentes.

Même avec des millions de requêtes transitant par le système, ThrottleX est resté efficace en matière de mémoire, maintenant une faible consommation de ressources.

4. Taux d'erreur – Moins de 0,001 %

À quoi ça sert de gérer un trafic massif si le système génère des erreurs partout ? Heureusement, ThrottleX a offert une fiabilité à toute épreuve :

  • Taux d'erreur : moins de 0,001 % des requêtes ont échoué ou ont été limitées inutilement, même dans des conditions de charge de pointe.

Cette fiabilité témoigne de l'efficacité de notre limitation adaptative du débit et du modèle de disjoncteur, qui ont permis d'éviter les surcharges du système et les pannes en cascade.


Ces benchmarks ne sont pas seulement impressionnants sur le papier : ils s'appuient sur des tests de résistance réels et montrent que ThrottleX est capable de gérer des charges de trafic extrêmes sans compromettre les performances.

Et voici le meilleur : vous pouvez l’essayer vous-même ! ?


Essayez-le vous-même

Tous le code et les configurations que j'ai utilisés pour ces benchmarks sont disponibles dans le Référentiel ThrottleX. Forkez-le, exécutez vos propres tests et voyez si vous pouvez aller encore plus loin. Le projet est open source et je suis toujours impatient de voir ce que la communauté peut apporter. Qu'il s'agisse d'améliorer les algorithmes ou d'optimiser un débit encore plus élevé, j'apprécie les contributions et les idées.

Lien vers cet exemple d'application, code de surveillance : https://github.com/neelp03/ThrottleX-Test

ThrottleX: Scaling to a Million Requests Per Second Without Breaking a Sweat


Section 5 : Leçons apprises – Ce qui nous a surpris

Construire quelque chose qui puisse gérer 1 million de requêtes par seconde a été une aventure folle, et en cours de route, nous avons rencontré des défis inattendus qui nous ont appris de précieuses leçons. Voici ce qui nous a le plus surpris et comment nous avons surmonté ces obstacles.

1. Go’s Garbage Collection – Un goulot d’étranglement silencieux

Lorsque nous avons commencé à évoluer, nous avons remarqué des pics aléatoires dans les temps de réponse lors de trafic intense. Après avoir étudié le problème, nous avons réalisé que le garbage collection (GC) de Go provoquait silencieusement des problèmes de performances.

  • Le problème : Avec des millions de goroutines volant, le GC était déclenché trop souvent, ce qui entraînait des pauses qui affectaient la latence.
  • Le correctif : Nous avons optimisé la manière dont la mémoire était allouée en implémentant des pools de mémoire personnalisés et en réutilisant des objets lorsque cela était possible. Cela a réduit la fréquence des cycles GC et lissé les performances lors des pics de trafic.

Leçon apprise : même si la gestion de la mémoire de Go est efficace, à grande échelle, vous devez micro-gérer la mémoire pour éviter les goulots d'étranglement des performances.

2. Retard de réplication Redis – La bombe à retardement cachée

Bien que Redis soit rapide, face à des millions de requêtes par seconde, nous avons rencontré un décalage de réplication. En cas de trafic intense, la capacité de Redis à répliquer les données entre les nœuds ne pouvait pas suivre la charge d'écriture.

  • Le problème : le retard de réplication Redis entraînait des retards dans la synchronisation des données entre les nœuds maître et réplica, ce qui entraînait des limites de débit incohérentes entre les systèmes distribués.
  • Le correctif : Nous avons réduit la fréquence de réplication et affiné Redis pour privilégier la haute disponibilité par rapport à la cohérence dans certains scénarios. Cela nous a donné de meilleures performances au prix de données obsolètes occasionnelles, mais pour la limitation du débit, ce compromis était acceptable.

Leçon apprise : Redis est une bête, mais à grande échelle, des compromis entre cohérence et disponibilité deviennent nécessaires pour maintenir des performances élevées.

3. Latence du réseau – Le tueur invisible

Lors des tests sur les nœuds distribués, nous avons constaté que la latence du réseau s'accumulait rapidement, en particulier lorsque les requêtes devaient voyager à travers les régions. À grande échelle, même quelques millisecondes de retard multipliées sur des millions de requêtes peuvent entraîner une grave dégradation des performances.

  • Le problème : La limitation de débit distribuée implique une communication constante entre les nœuds et vers Redis, et même de minuscules retards de réseau s'ajoutent.
  • Le correctif : Nous avons optimisé le système en localisant autant de logique de limitation de débit que possible, minimisant ainsi le nombre de déplacements vers Redis. En traitant d'abord les demandes localement et en synchronisant uniquement l'état périodiquement, nous avons réduit la dépendance globale aux appels réseau.

Leçon apprise : Minimiser les appels réseau est crucial pour les systèmes distribués. Moins vous dépendez de la communication externe, plus votre système sera résilient et rapide.

4. Limitation de débit adaptative – Trouver l’équilibre

Bien que la limitation adaptative du débit ait changé la donne, trouver le juste équilibre entre autoriser les augmentations de trafic et maintenir la protection a été plus délicat que prévu.

  • Le problème : Au début, les limites de tarifs étaient ajustées de manière trop agressive, autorisant trop de trafic pendant les pics, ce qui a conduit à des surcharges temporaires.
  • Le correctif : Nous avons modifié l'algorithme pour prendre en compte les tendances de trafic à plus long terme, lissant ainsi les ajustements tarifaires au fil du temps. Cela a évité les fluctuations brutales du trafic et a donné au système plus de marge de manœuvre lors de pics de trafic soutenus.

Leçon apprise : L'adaptation est puissante, mais elle doit être affinée pour éviter une correction excessive. Trop d'ajustement peut être aussi dangereux que pas assez.


La création et la mise à l'échelle de ThrottleX nous ont appris que les performances à grande échelle consistent à trouver le bon équilibre : équilibrer l'utilisation de la mémoire, la latence du réseau, la réplication et les limites de débit. Chaque optimisation impliquait des compromis, mais chaque défi nous poussait à construire un système plus résilient et plus rapide.


Conclusion – À vous de jouer : poussez ThrottleX encore plus loin

ThrottleX est désormais un limiteur de débit distribué éprouvé, capable de gérer des charges de trafic extrêmes. Mais il y a toujours de la place pour plus ! Que vous souhaitiez apporter de nouvelles fonctionnalités, le tester dans différentes conditions ou le modifier pour des performances encore meilleures, le référentiel ThrottleX est ouvert et vous attend.

Repoussons les limites ensemble et voyons jusqu'où nous pouvons aller.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn