QUIC en action: comment Uber l'a mis en œuvre pour optimiser les performances

Le protocole QUIC est extrêmement intéressant à regarder, nous aimons donc écrire à ce sujet. Mais si les publications précédentes sur QUIC étaient davantage de caractère et de matériel historiques (histoire locale, si vous voulez), alors aujourd'hui nous sommes heureux de publier une interprétation différente - nous parlerons de l'application réelle du protocole en 2019. Et il ne s'agit pas d'une petite infrastructure basée dans un garage conditionnel, mais d'Uber, qui fonctionne presque partout dans le monde. Comment les ingénieurs de l'entreprise ont-ils décidé d'utiliser QUIC dans la production, comment ils ont testé et ce qu'ils ont vu après leur entrée dans la production - sous la coupe.
Les photos sont cliquables. Bonne lecture!



Uber est une échelle mondiale, à savoir 600 villes de présence, dans chacune desquelles l'application repose entièrement sur Internet sans fil de plus de 4500 opérateurs mobiles. Les utilisateurs s'attendent à ce que l'application fonctionne non seulement rapidement, mais en temps réel - pour cela, l'application Uber a besoin d'une faible latence et d'une connexion très fiable. Hélas, la pile HTTP / 2 ne se sent pas bien dans les réseaux sans fil dynamiques et sujets aux pertes. Nous avons réalisé que dans ce cas, les faibles performances sont directement liées aux implémentations TCP dans les noyaux des systèmes d'exploitation.

Pour résoudre le problème, nous avons appliqué QUIC , un protocole moderne avec multiplexage de canaux, qui nous donne plus de contrôle sur les performances du protocole de transport. Le groupe de travail de l' IETF standardise actuellement QUIC en HTTP / 3 .

Après des tests détaillés, nous sommes arrivés à la conclusion que l'implémentation de QUIC dans notre application réduira les retards de «queue» par rapport à TCP. Nous avons observé une diminution de l'ordre de 10 à 30% pour le trafic HTTPS sur l'exemple des applications conducteur et passager. QUIC nous a également donné un contrôle de bout en bout sur les packages personnalisés.

Dans cet article, nous partageons notre expérience sur l'optimisation de TCP pour les applications Uber à l'aide d'une pile qui prend en charge QUIC.

Dernier mot de la technologie: TCP


Aujourd'hui, TCP est le protocole de transport le plus utilisé pour fournir du trafic HTTPS sur Internet. TCP fournit un flux d'octets fiable, faisant ainsi face à la congestion du réseau et à la perte de couche liaison. L'utilisation répandue de TCP pour le trafic HTTPS s'explique par l'omniprésence du premier (presque tous les systèmes d'exploitation contiennent TCP), la disponibilité sur la plupart de l'infrastructure (par exemple, sur les équilibreurs de charge, les proxys HTTPS et les CDN) et la fonctionnalité prête à l'emploi, qui est disponible sur la plupart des plates-formes et les réseaux.

La plupart des utilisateurs utilisent notre application en déplacement, et les retards de fin TCP sont loin des exigences en temps réel de notre trafic HTTPS. En termes simples, les utilisateurs du monde entier ont été confrontés à cela - la figure 1 montre les retards dans les grandes villes:


Figure 1. L'ampleur des retards de «queue» varie dans les principales villes où Uber opère.

Malgré le fait qu'il y ait eu plus de retards dans les réseaux indiens et brésiliens qu'aux États-Unis et en Grande-Bretagne, les retards de queue sont beaucoup plus importants que les retards moyens. Et cela est vrai même pour les États-Unis et la Grande-Bretagne.

Performances TCP en direct


TCP a été créé pour les réseaux câblés , c'est-à-dire en mettant l'accent sur des liaisons bien prévisibles. Cependant, les réseaux sans fil ont leurs propres caractéristiques et difficultés. Premièrement, les réseaux sans fil sont sensibles aux pertes dues aux interférences et à l'atténuation du signal. Par exemple, les réseaux Wi-Fi sont sensibles aux micro-ondes, au Bluetooth et à d'autres ondes radio. Les réseaux cellulaires souffrent d'une perte de signal (perte de chemin ) due à la réflexion / absorption du signal par les objets et les bâtiments, ainsi qu'aux interférences des tours cellulaires voisines. Cela entraîne des retards plus importants (4 à 10 fois) et une variété de retards aller-retour (RTT) et de pertes de paquets par rapport à une connexion filaire.

Pour lutter contre les fluctuations et les pertes de bande passante, les réseaux cellulaires utilisent généralement de grands tampons pour les rafales de trafic. Cela peut entraîner une priorité excessive, ce qui signifie des délais plus longs. Très souvent, TCP traite une telle séquence comme une perte due à un dépassement de délai, donc TCP est enclin à faire un relais et à remplir ainsi le tampon. Ce problème est connu sous le nom de bufferbloat ( mise en mémoire tampon excessive du réseau, gonflement du tampon ), et c'est un problème très grave de l' Internet moderne.

Enfin, les performances du réseau cellulaire varient en fonction de l'opérateur, de la région et de l'heure. Dans la figure 2, nous avons collecté les retards médians du trafic HTTPS sur les cellules dans une plage de 2 kilomètres. Les données sont collectées pour les deux plus grands opérateurs de téléphonie mobile de Delhi, en Inde. Comme vous pouvez le voir, les performances varient d'une cellule à l'autre. De plus, les performances d'un opérateur sont différentes de celles du second. Cela est influencé par des facteurs tels que les modèles d'accès au réseau, en tenant compte du temps et de l'emplacement, de la mobilité des utilisateurs, ainsi que de l'infrastructure du réseau, en tenant compte de la densité des tours et du rapport des types de réseaux (LTE, 3G, etc.).


Figure 2. Délais pour un exemple de rayon de 2 km. Delhi, Inde.

De plus, les performances des réseaux cellulaires varient au fil du temps. La figure 3 montre le délai médian par jour de la semaine. Nous avons également observé une différence à plus petite échelle - en un jour et une heure.


Figure 3. Les retards de queue peuvent varier considérablement selon les jours, mais avec le même opérateur.

Tout ce qui précède conduit au fait que les performances TCP sont inefficaces dans les réseaux sans fil. Cependant, avant de chercher des alternatives au TCP, nous avons voulu développer une compréhension précise des points suivants:
  • TCP est-il le principal responsable des retards dans nos applications?
  • Les réseaux modernes ont-ils des retards aller-retour (RTT) importants et variés?
  • Quel est l'effet de la perte de performances RTT et TCP?

Analyse des performances TCP


Pour comprendre comment nous avons analysé les performances TCP, rappelons brièvement comment TCP transfère les données d'un expéditeur vers un récepteur. Tout d'abord, l'expéditeur établit une connexion TCP en effectuant une négociation à trois: l'expéditeur envoie un paquet SYN, attend un paquet SYN-ACK du destinataire, puis envoie un paquet ACK. Des deuxième et troisième passes supplémentaires sont nécessaires pour créer une connexion TCP. Le destinataire accuse réception de chaque paquet (ACK) pour assurer une livraison fiable.

Si un paquet ou un ACK est perdu, l'expéditeur retransmet après un délai d'attente (RTO, délai de retransmission ). Le RTO est calculé dynamiquement sur la base de divers facteurs, par exemple, le délai RTT attendu entre l'expéditeur et le récepteur.


Figure 4. L'échange de paquets TCP / TLS comprend un mécanisme de retransmission.

Pour déterminer le fonctionnement de TCP dans nos applications, nous avons surveillé les paquets TCP avec tcpdump pendant une semaine sur le trafic de combat provenant des serveurs frontaliers indiens. Nous avons ensuite analysé les connexions TCP à l'aide de tcptrace . De plus, nous avons créé une application Android qui envoie du trafic émulé vers un serveur de test, en imitant le plus possible le trafic réel. Des smartphones avec cette application ont été distribués à plusieurs employés qui ont collecté des journaux pendant plusieurs jours.

Les résultats des deux expériences étaient cohérents l'un avec l'autre. Nous avons constaté des retards RTT élevés; les valeurs de queue étaient presque 6 fois plus élevées que la valeur médiane; valeur arithmétique moyenne des retards - plus de 1 seconde. De nombreuses connexions ont subi des pertes, entraînant la retransmission par TCP de 3,5% de tous les paquets. Dans les zones de congestion, comme les aéroports et les gares, nous avons observé une perte de 7%. De tels résultats jettent le doute sur la sagesse conventionnelle selon laquelle les systèmes de retransmission avancés utilisés dans les réseaux cellulaires réduisent considérablement les pertes de transport. Voici les résultats des tests de l'application «simulateur»:
Mesures du réseauLes valeurs
RTT, millisecondes [50%, 75%, 95%, 99%][350, 425, 725, 2300]
Écart RTT, secondes~ 1,2 s en moyenne
Perte de paquets dans les connexions instablesEn moyenne ~ 3,5% (7% dans les zones de congestion)

Près de la moitié de ces connexions ont eu au moins une perte de paquets, dont la plupart étaient des paquets SYN et SYN-ACK. La plupart des implémentations TCP utilisent une valeur RTO de 1 seconde pour les paquets SYN, qui augmente de façon exponentielle pour les pertes ultérieures. Le temps de chargement des applications peut augmenter en raison du fait que TCP aura besoin de plus de temps pour établir des connexions.

Dans le cas des paquets de données, des RTO élevés réduisent considérablement l'utilisation utile du réseau en présence de pertes temporaires dans les réseaux sans fil. Nous avons constaté que le temps de retransmission moyen est d'environ 1 seconde avec un retard de queue de près de 30 secondes. Ces retards élevés au niveau TCP ont provoqué des délais d'attente et des tentatives HTTPS, ce qui a encore augmenté la latence et l'inefficacité du réseau.

Alors que le 75e centile du RTT mesuré était d'environ 425 ms, le 75e centile pour TCP était de près de 3 secondes. Cela indique que la perte a forcé TCP à effectuer 7 à 10 passes afin de transmettre avec succès les données. Cela peut être dû à un calcul RTO inefficace, à l'incapacité de TCP à répondre rapidement à la perte des derniers paquets de la fenêtre et à l'inefficacité de l'algorithme de contrôle de congestion, qui ne fait pas de distinction entre les pertes sans fil et les pertes dues à la congestion du réseau. Voici les résultats du test de perte TCP:
Statistiques de perte de paquets TCPValeur
Pourcentage de connexions avec au moins 1 perte de paquets45%
Pourcentage de connexions avec perte lors de l'établissement de la connexion30%
Le pourcentage de connexions avec perte lors de l'échange de données76%
Distribution du délai de retransmission, en secondes [50%, 75%, 95%, 99%][1, 2.8, 15, 28]
Distribution des retransmissions pour un seul paquet ou segment TCP[1,3,6,7]

Application QUIC


Conçu à l'origine par Google, QUIC est un protocole de transport moderne et multithread qui s'exécute sur UDP. À l'heure actuelle, QUIC est en cours de normalisation (nous avons déjà écrit qu'il existe, pour ainsi dire, deux versions de QUIC, les curieux peuvent suivre le lien - environ Translator). Comme le montre la figure 5, QUIC est hébergé sous HTTP / 3 (en fait, HTTP / 2 en plus de QUIC - il s'agit de HTTP / 3, qui est maintenant fortement normalisé). Il remplace partiellement les couches HTTPS et TCP, en utilisant UDP pour former des paquets. QUIC prend uniquement en charge le transfert de données sécurisé, car TLS est entièrement intégré à QUIC.


Figure 5: QUIC fonctionne sous HTTP / 3, en remplacement de TLS, qui fonctionnait auparavant sous HTTP / 2.

Ci-dessous, nous énumérons les raisons qui nous ont convaincus d'utiliser QUIC pour renforcer TCP:
  • Configuration de la connexion 0-RTT. QUIC permet la réutilisation des autorisations des connexions précédentes, réduisant le nombre de prises de contact de sécurité. À l'avenir, TLS1.3 prendra en charge 0-RTT, mais une négociation TCP à trois voies sera toujours nécessaire.
  • Surmonter le blocage HoL. HTTP / 2 utilise une connexion TCP pour chaque client pour améliorer les performances, mais cela peut conduire à un bloc HoL (tête de ligne). QUIC simplifie le multiplexage et fournit des requêtes à l'application indépendamment les unes des autres.
  • gestion de la congestion. QUIC est au niveau de l'application, ce qui facilite la mise à jour de l'algorithme de transport principal, qui contrôle l'envoi, en fonction des paramètres du réseau (quantité de perte ou RTT). La plupart des implémentations TCP utilisent l'algorithme CUBIC , qui n'est pas optimal pour le trafic sensible aux retards. Des algorithmes nouvellement développés tels que BBR modélisent plus précisément le réseau et optimisent la latence. QUIC vous permet d'utiliser BBR et de mettre à jour cet algorithme à mesure qu'il s'améliore .
  • compenser les pertes. QUIC appelle deux TLP ( sonde de perte de queue ) avant que le RTO ne se déclenche - même lorsque les pertes sont très visibles. Ceci est différent des implémentations TCP. TLP retransmet principalement le dernier paquet (ou le nouveau, le cas échéant) pour déclencher un réapprovisionnement rapide. Le traitement du retard de queue est particulièrement utile pour la façon dont Uber fonctionne avec le réseau, à savoir pour les transmissions de données courtes, épisodiques et sensibles au retard.
  • ACK optimisé. Étant donné que chaque paquet a un numéro de série unique, il n'y a aucun problème à distinguer les paquets lorsqu'ils sont relayés. Les paquets ACK contiennent également du temps pour traiter le paquet et générer des ACK côté client. Ces fonctionnalités garantissent que QUIC calcule RTT plus précisément. Le QUIC ACK prend en charge jusqu'à 256 plages NACK , aidant l'expéditeur à être plus résilient à l'échange de paquets et à utiliser moins d'octets dans le processus. ACK sélectif ( SACK ) dans TCP ne résout pas ce problème dans tous les cas.
  • migration de connexion. Les connexions QUIC sont identifiées par un ID 64 bits, donc si le client change d'adresse IP, vous pouvez continuer à utiliser l'ID de l'ancienne connexion sur la nouvelle adresse IP, sans interruption. Il s'agit d'une pratique très courante pour les applications mobiles lorsqu'un utilisateur bascule entre les connexions Wi-Fi et cellulaires.

Alternatives à QUIC


Nous avons examiné des approches alternatives pour résoudre le problème avant de choisir QUIC.

Tout d'abord, nous avons essayé de déployer des PoP (Points of Presence) TPC pour compléter les connexions TCP plus près des utilisateurs. Essentiellement, les PoP mettent fin à la connexion TCP avec l'appareil mobile plus proche du réseau cellulaire et procurent le trafic proxy à l'infrastructure d'origine. En fermant TCP plus près, nous pouvons potentiellement réduire RTT et nous assurer que TCP sera plus réactif aux environnements sans fil dynamiques. Cependant, nos expériences ont montré que la plupart du temps, le RTT et les pertes proviennent des réseaux cellulaires et l'utilisation de PoP n'apporte pas une amélioration significative des performances.

Nous avons également cherché à régler les paramètres TCP. La configuration de la pile TCP sur nos serveurs de périphérie hétérogènes a été difficile car TCP a des implémentations disparates entre différentes versions de système d'exploitation. Il était difficile de l'implémenter et de tester différentes configurations de réseau. La configuration de TCP directement sur les appareils mobiles n'a pas été possible en raison d'un manque d'autorité. Plus important encore, les puces telles que les connexions avec 0-RTT et la prédiction RTT améliorée sont essentielles à l'architecture du protocole, et il n'est donc pas possible d'obtenir des avantages significatifs simplement en configurant TCP.

Enfin, nous avons évalué plusieurs protocoles basés sur UDP qui résolvent les problèmes de streaming vidéo - nous voulions savoir si ces protocoles seraient utiles dans notre cas. Hélas, ils manquaient de nombreux paramètres de sécurité et ils avaient également besoin d'une connexion TCP supplémentaire pour les métadonnées et les informations de contrôle.

Notre recherche a montré que QUIC est presque le seul protocole capable de résoudre le problème du trafic Internet, tout en tenant compte à la fois de la sécurité et des performances.

Intégration QUIC dans la plateforme


Pour intégrer avec succès QUIC et améliorer les performances des applications dans de mauvaises conditions de communication, nous avons remplacé l'ancienne pile (HTTP / 2 sur TLS / TCP) par le protocole QUIC. Nous avons utilisé la bibliothèque réseau Cronet de Chromium Projects , qui contient la version originale Google du protocole - gQUIC. Cette implémentation est également constamment améliorée pour suivre la dernière spécification IETF.

Tout d'abord, nous avons intégré Cronet dans nos applications Android pour ajouter la prise en charge QUIC. L'intégration a été réalisée de manière à minimiser les coûts de migration. Au lieu de remplacer complètement l'ancienne pile réseau qui utilisait la bibliothèque OkHttp , nous avons intégré Cronet SOUS le framework API OkHttp. En intégrant de cette manière, nous avons évité des changements dans nos appels réseau (que Retrofit utilise) au niveau de l'API.

Semblable à l'approche des appareils Android, nous avons implémenté Cronet dans les applications Uber pour iOS, interceptant le trafic HTTP provenant des API réseau à l'aide de NSURLProtocol . Cette abstraction, fournie par la fondation iOS, traite les données URL spécifiques au protocole et garantit que nous pouvons intégrer Cronet dans nos applications iOS sans coûts de migration importants.

Quic terminée sur Google Cloud Balancers


Côté backend, la terminaison QUIC est fournie par l'infrastructure d'équilibrage de charge Google Cloud, qui utilise des en - têtes alt-svc dans les réponses pour prendre en charge QUIC. En général, l'équilibreur ajoute l'en-tête alt-svc à chaque demande HTTP et il valide déjà la prise en charge QUIC pour le domaine. Lorsque le client Cronet reçoit une réponse HTTP avec cet en-tête, il utilise QUIC pour les requêtes HTTP suivantes vers ce domaine. Dès que l'équilibreur a terminé QUIC, notre infrastructure envoie explicitement cette action via HTTP2 / TCP à nos centres de données.

Performance: Résultats


Des performances exceptionnelles sont la principale raison de notre recherche d'un meilleur protocole. Tout d'abord, nous avons créé un stand avec émulation de réseau pour découvrir comment QUIC se comportera avec différents profils de réseau. Pour tester les performances de QUIC dans des réseaux réels, nous avons expérimenté à New Delhi, en utilisant un trafic réseau émulé très similaire aux appels HTTP dans une application de passager.

Expérience 1


Inventaire pour l'expérience:
  • Testez les appareils Android avec les piles OkHttp et Cronet pour vous assurer que nous envoyons le trafic HTTPS via TCP et QUIC, respectivement;
  • un serveur d'émulation basé sur Java qui envoie le même type d'en-têtes HTTPS dans les réponses et charge les appareils clients pour recevoir des demandes de leur part;
  • Des proxy cloud physiquement situés près de l'Inde pour compléter les connexions TCP et QUIC. Bien que nous ayons utilisé le proxy inverse sur NGINX pour terminer TCP, il était difficile de trouver le proxy inverse open source pour QUIC. Nous avons construit le proxy inverse pour QUIC nous-mêmes, en utilisant la pile QUIC de base de Chromium et l'avons publié en chrome comme open source.


Figure 6. Le jeu de voyage pour les tests TCP vs QUIC était composé d'appareils Android avec OkHttp et Cronet, de proxys cloud pour mettre fin aux connexions et d'un serveur d'émulation.

Expérience 2


Lorsque Google a rendu QUIC disponible à l'aide de Google Cloud Load Balancing , nous avons utilisé le même inventaire, mais avec une modification: au lieu de NGINX, nous avons pris des équilibreurs Google pour compléter les connexions TCP et QUIC à partir des appareils, ainsi que pour acheminer le trafic HTTPS vers le serveur d'émulation. . Les équilibreurs sont distribués dans le monde entier, mais utilisent le serveur PoP le plus proche de l'appareil (grâce à la géolocalisation).


Figure 7. Dans la deuxième expérience, nous voulions comparer le délai d'achèvement TCP et QUIC: en utilisant Google Cloud et en utilisant notre proxy cloud.

En conséquence, plusieurs révélations nous attendaient:
  • La terminaison PoP a amélioré les performances TCP. Étant donné que les équilibreurs complètent la connexion TCP plus près des utilisateurs et sont parfaitement optimisés, cela se traduit par une RTT inférieure, ce qui améliore les performances TCP. QUIC , TCP ( 10-30 ).
  • (hops) . QUIC- ( 50 ), , – 15%- 20%- 99 TCP. , – (bottleneck) .


8. , QUIC TCP.


, QUIC Android iOS-. A/B , QUIC Uber. , , .

(95 99 ) – LTE, 3G, 2G.

9. QUIC TCP .


, – QUIC , , :


, , 80% QUIC , 15% QUIC TCP. , - , Cronet TCP , UDP- . , QUIC.

QUIC


, . . , , TCP QUIC . QUIC- .

, .

Source: https://habr.com/ru/post/fr463073/


All Articles