Il est extrêmement intéressant d'observer le protocole QUIC, c'est pourquoi nous aimons en parler. Cependant, contrairement aux précédentes publications sur QUIC qui avaient un caractère plus historique (local, si vous voulez) et portaient sur la théorie, nous sommes aujourd'hui ravis de publier une traduction d'un autre type – il s'agira de l'application réelle du protocole en 2019. Et ce n'est pas une petite infrastructure basée dans un garage, mais Uber, qui opère presque partout dans le monde. Comment les ingénieurs de l'entreprise ont décidé d'utiliser QUIC en production, comment ils ont effectué des tests et ce qu'ils ont observé après le déploiement en production – lisez la suite.
Les images sont cliquables. Bonne lecture!
Uber – c'est un échelle mondiale, avec pas moins de 600 villes de présence, où l'application repose entièrement sur Internet sans fil de plus de 4500 opérateurs de téléphonie mobile. Les utilisateurs s'attendent à ce que l'application fonctionne non seulement rapidement, mais en temps réel – pour garantir cela, l'application Uber a besoin de latences faibles et d'une connexion très fiable. Malheureusement, la pile se sent mal dans les réseaux sans fil dynamiques et sujets à perte. Nous avons compris que, dans ce cas, la faible performance est directement liée aux implémentations de TCP dans les noyaux des systèmes d'exploitation.
Pour résoudre ce problème, nous avons appliqué , un protocole moderne avec multiplexage de canaux, qui nous donne un meilleur contrôle sur la performance du protocole de transport. Actuellement, le groupe de travail normalise QUIC en tant que .
Après des tests approfondis, nous sommes parvenus à la conclusion que l'intégration de QUIC dans notre application réduira les retards « de queue » par rapport au TCP. Nous avons observé une réduction allant de 10 à 30 % pour le trafic HTTPS, en prenant en exemple les applications des conducteurs et des passagers. De plus, QUIC nous a donné un contrôle de bout en bout sur les paquets des utilisateurs.
Dans cet article, nous partageons notre expérience d'optimisation de TCP pour les applications Uber à l'aide d'une pile qui prend en charge QUIC.
Le dernier mot de la technique : TCP
Aujourd'hui, TCP est le protocole de transport le plus utilisé pour la livraison du trafic HTTPS sur Internet. TCP assure un flux de données fiable, gérant ainsi la congestion du réseau et les pertes au niveau de la couche de liaison. L'utilisation répandue de TCP pour le trafic HTTPS s'explique par la prévalence du premier (près de chaque système d'exploitation comprend TCP), sa disponibilité sur la majorité de l'infrastructure (par exemple, sur les équilibreurs de charge, les proxies HTTPS et les CDN) et la fonctionnalité « prête à l'emploi » accessible sur presque toutes les plateformes et réseaux.
La plupart des utilisateurs utilisent notre application en déplacement, et les délais de « queue » TCP étaient loin de répondre aux exigences de notre trafic HTTPS en temps réel. En d'autres termes, c'était un problème rencontré par des utilisateurs du monde entier – la Figure 1 révèle les délais dans les grandes villes :
Figure 1. La magnitude des délais de « queue » varie dans les principales villes où Uber est présent.
Bien que les délais dans les réseaux indiens et brésiliens aient été plus élevés que ceux des États-Unis et du Royaume-Uni, les délais de queue étaient significativement plus importants que les délais moyens. Et c'est également le cas pour les États-Unis et le Royaume-Uni.
Performances de TCP sur air
TCP a été conçu pour les réseaux câblés , c'est-à-dire avec un accent sur les liaisons bien prévisibles. Cependant, les réseaux sans fil ont leurs propres caractéristiques et défis. 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 de pertes de signal () dues à la réflexion / absorption du signal par des objets et des bâtiments, ainsi qu'à des provenant de . Cela conduit à des délais de transit (RTT) et à des pertes de paquets beaucoup plus significatifs (de 4 à 10 fois) et variés par rapport à une connexion câblée. suremballement réseau, gonflement de tampon
), et c'est un problème très (), et c'est un problème très d'Internet moderne.
Enfin, la performance du réseau mobile varie en fonction de l'opérateur, de la région et du moment. Dans la figure 2, nous avons rassemblé les latences médianes du trafic HTTPS par cellule dans un rayon de 2 kilomètres. Les données ont été collectées pour deux des plus grands opérateurs de téléphonie mobile à Delhi, en Inde. Comme on peut le constater, la performance varie d'une cellule à l'autre. De plus, la performance d'un opérateur diffère de celle de l'autre. Cela est influencé par des facteurs tels que les modèles de connexion en tenant compte du temps et de la localisation, la mobilité des utilisateurs, ainsi que l'infrastructure réseau en tenant compte de la densité des tours et du ratio des types de réseau (LTE, 3G, etc.).
Figure 2. Latences dans un rayon de 2 kilomètres. Delhi, Inde.
De plus, la performance des réseaux mobiles varie dans le temps. Dans la figure 3, nous avons représenté la latence médiane par jour de la semaine. Nous avons également observé des différences à une échelle plus petite - au sein d'une même journée et heure.
Figure 3. Les latences de fin de queue peuvent varier considérablement d'un jour à l'autre, même pour le même opérateur.
Tout ce qui précède entraîne une inefficacité de la performance TCP dans les réseaux sans fil. Cependant, avant de rechercher des alternatives au TCP, nous souhaitons évaluer précisément les points suivants :
- le TCP est-il le principal responsable des latences de fin de queue dans nos applications ?
- Les réseaux modernes présentent-ils des latences circulaires (RTT) significatives et variées ?
- Quel est l'impact du RTT et des pertes sur la performance TCP ?
Analyse de la performance TCP
Pour comprendre comment nous avons analysé la performance TCP, rappelons brièvement comment le TCP transmet des données de l'expéditeur au destinataire. Dans un premier temps, l'expéditeur établit une connexion TCP en réalisant un processus de trois étapes. : l'expéditeur envoie un paquet SYN, attend un paquet SYN-ACK du destinataire, puis envoie un paquet ACK. Les deux passages additionnels sont consacrés à la création de la connexion TCP. Le destinataire confirme la réception de chaque paquet (ACK) afin d'assurer une livraison fiable.
Si un paquet ou un ACK est perdu, l'expéditeur retransmet après un délai d'attente (RTO, ). Le RTO est calculé dynamiquement, en fonction de divers facteurs, par exemple en se basant sur la latence RTT attendue entre l'expéditeur et le destinataire.
Figure 4. TCP/TLS packet exchanges include retransmission mechanisms.
To determine how TCP worked in our applications, we tracked TCP packets using for a week on live traffic coming from Indian border servers. We then analyzed TCP connections using Additionally, we created an Android application that sends emulated traffic to a test server, closely mimicking real traffic. Smartphones with this application were distributed to several employees who collected logs over several days.
The results of both experiments were correlated. We observed high RTT delays; tail values were almost 6 times higher than the median; the average delay was over 1 second. Many connections experienced losses, causing TCP to retransmit 3.5% of all packets. In congested areas like airports and train stations, we observed 7% losses. These results cast doubt on the common belief that advanced retransmission schemes used in cellular networks Network metrics
RTT, milliseconds [50%, 75%, 95%, 99%]
Valeurs
RTT divergence, seconds
[350, 425, 725, 2300]
On average ~1.2 sec
Packet loss in unstable connections
On average ~3.5% (7% in congested areas)
In almost half of these connections, there was at least one packet loss, mostly SYN and SYN-ACK packets. Most TCP implementations use an RTO value of 1 second for SYN packets, which increases exponentially for subsequent losses. Application load times can increase because TCP takes longer to establish connections.
In the case of data packets, high RTO values greatly reduce the effective utilization of the network in the presence of temporary losses in wireless networks. We found that the average retransmit time is about 1 second with tail delays of almost 30 seconds. Such high TCP-level delays caused HTTPS timeouts and repeated requests, further increasing latency and network inefficiency.
Dans le cas des paquets de données, des valeurs élevées de RTO réduisent considérablement l'utilisation efficace du réseau en présence de pertes temporaires dans les réseaux sans fil. Nous avons constaté que le temps moyen de retransmission est d'environ 1 seconde, avec un délai de queue d'environ 30 secondes. De telles latences élevées au niveau TCP provoquaient des timeouts HTTPS et des requêtes répétées, ce qui augmentait encore la latence et l'inefficacité du réseau.
Alors que le 75e percentile des RTT mesurés était d'environ 425 ms, le 75e percentile pour TCP était presque de 3 secondes. Cela suggère que les pertes obligeaient TCP à effectuer 7 à 10 passes pour transmettre des données avec succès. Cela peut être dû à un calcul inefficace du RTO, rendant difficile la réaction rapide de TCP en cas de perte. dans la fenêtre et à l'inefficacité de l'algorithme de contrôle de congestion, qui ne fait pas la distinction entre pertes sans fil et pertes dues à une surcharge du réseau. Voici les résultats des tests de pertes TCP :
Statistiques de perte de paquets TCP
Valeur
Pourcentage de connexions avec au moins 1 perte de paquet
45%
Pourcentage de connexions avec pertes lors de l'établissement de la connexion
30%
Pourcentage de connexions avec pertes lors de l'échange de données
76%
Distribution des délais de retransmission, secondes [50 %, 75 %, 95 %, 99 %]
[1, 2.8, 15, 28]
Distribution du nombre de retransmissions pour un paquet ou un segment TCP
[1,3,6,7]
Application de QUIC
Initialement conçu par Google, QUIC est un protocole de transport moderne multi-flux qui fonctionne au-dessus de UDP. À l'heure actuelle, QUIC est (nous avons déjà mentionné qu'il existe en quelque sorte deux versions de QUIC, les curieux – note du traducteur). Comme le montre la Figure 5, QUIC s'est situé sous HTTP/3 (en fait, HTTP/2 au-dessus de QUIC est HTTP/3, qui est actuellement en cours de normalisation intensive). Il remplace en partie les couches HTTPS et TCP, utilisant UDP pour former des paquets. QUIC ne prend en charge que la transmission sécurisée des données, puisque TLS est entièrement intégré dans QUIC.

Figure 5 : QUIC fonctionne sous HTTP/3, remplaçant TLS, qui précédemment fonctionnait sous HTTP/2.
Voici les raisons qui nous ont convaincus d'utiliser QUIC pour renforcer TCP :
- établissement de connexion 0-RTT. QUIC permet la réutilisation des autorisations des connexions précédentes, réduisant le nombre de handshakes de sécurité. À l'avenir, supportera le 0-RTT, cependant, le handshake TCP en trois étapes sera toujours obligatoire.
- surmontant le blocage HoL. HTTP/2 utilise une seule connexion TCP pour chaque client afin d'améliorer les performances, mais cela peut mener à un blocage HoL (head-of-line). QUIC simplifie le multiplexage et livre les requêtes à l'application de manière indépendante les unes des autres.
- gestion de la congestion. QUIC fonctionne au niveau des applications, permettant de mettre à jour plus facilement l'algorithme de transport principal, qui gère l'envoi en fonction des paramètres du réseau (taux de pertes ou RTT). La plupart des réalisations TCP utilisent l'algorithme , qui n'est pas optimal pour le trafic sensible à la latence. Des algorithmes récemment développés tels que modélisent plus précisément le réseau et optimisent les latences. QUIC permet d'utiliser BBR et de mettre à jour cet algorithme au fur et à mesure de son .
- en cas de perte. QUIC déclenche deux TLP () avant que le RTO ne s'active – même lorsque les pertes sont très perceptibles. Cela diffère des réalisations TCP. TLP retransmet principalement le dernier paquet (ou un nouveau, s'il y en a un) pour déclencher un remplissage rapide. Le traitement des latences de fin de chaîne est particulièrement utile pour la façon dont Uber interagit avec le réseau, notamment pour le transfert de données courts, épisodiques et sensibles à la latence.
- ACK optimisé. Étant donné que chaque paquet a un numéro de séquence unique, il n'y a pas de problème des paquets lors de leur retransmission. Les paquets ACK contiennent également le temps de traitement du paquet et la génération de l'ACK du côté client. Ces caractéristiques garantissent que QUIC calcule le RTT de manière plus précise. Les ACK dans QUIC prennent en charge jusqu'à 256 plages , aidant l'expéditeur à être plus résistant à la réorganisation de paquets et à utiliser moins de bytes dans le processus. Les ACK sélectifs () dans TCP ne résolvent pas ce problème dans tous les cas.
- migration de connexion. Les connexions QUIC sont identifiées par un ID de 64 bits, de sorte que si le client change d'adresses IP, l'ID de l'ancienne connexion peut être utilisé sur la nouvelle adresse IP sans interruption. C'est une pratique très courante pour les applications mobiles lorsqu'un utilisateur bascule entre le Wi-Fi et les connexions cellulaires.
Alternatives à QUIC
Nous avons examiné des approches alternatives pour résoudre le problème avant de choisir QUIC.
Nous avons d'abord essayé de déployer des Points de Présence TPC (TCP Points of Presence) pour terminer les connexions TCP plus près des utilisateurs. En gros, les PoPs terminent la connexion TCP avec l'appareil mobile plus près du réseau cellulaire et transmettent le trafic à l'infrastructure d'origine. En terminant le TCP plus près, nous pouvons potentiellement réduire le RTT et être assurés que le TCP réagira plus activement à l'environnement sans fil dynamique. Cependant, nos expériences ont montré que, dans la plupart des cas, le RTT et les pertes proviennent des réseaux cellulaires et que l'utilisation des PoPs ne fournit pas d'amélioration significative des performances.
Nous avons également exploré l'optimisation des paramètres TCP. La configuration de la pile TCP sur nos serveurs de frontière hétérogènes a été difficile, car TCP a des mises en œuvre incompatibles dans différentes versions de systèmes d'exploitation. Il a été difficile de l'implémenter et de tester différentes configurations réseau. Configurer le TCP directement sur les dispositifs mobiles était impossible en raison d'un manque de privilèges. Plus important encore, des fonctionnalités comme les connexions 0-RTT et la prévision améliorée du RTT sont cruciales pour l'architecture du protocole et il est donc impossible d'obtenir un avantage significatif en se contentant de régler le 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. Malheureusement, ils manquaient cruellement de nombreux réglages de sécurité, et ils nécessitaient également une connexion TCP supplémentaire pour les métadonnées et les informations de contrôle.
Nos recherches ont montré que QUIC est à peu près le seul protocole qui peut aider à résoudre le problème du trafic Internet tout en tenant compte à la fois de la sécurité et des performances.
Intégration de QUIC dans la plateforme
Pour intégrer QUIC avec succès et améliorer les performances de l'application dans des conditions de mauvaise connexion, nous avons remplacé l'ancienne pile (HTTP/2 sur TLS/TCP) par le protocole QUIC. Nous avons utilisé la bibliothèque réseau de , qui contient la version originale de Google du protocole – gQUIC. Cette implémentation est également constamment améliorée pour suivre les dernières spécifications de l'IETF.
Nous avons d'abord intégré Cronet dans nos applications Android pour ajouter le support de QUIC. L'intégration a été effectuée de manière à minimiser au maximum les coûts de migration. Au lieu de remplacer complètement l'ancienne pile réseau qui utilisait la bibliothèque , nous avons intégré Cronet SOUS le cadre de l'API OkHttp. En procédant ainsi, nous avons évité des modifications dans nos appels réseau (qui utilisent ) au niveau de l'API.
Tout comme pour les appareils Android, nous avons intégré Cronet dans les applications Uber sous iOS, en interceptant le trafic HTTP des , en utilisant . Cette abstraction, fournie par iOS Foundation, gère 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 significatifs.
Terminaison de QUIC sur les équilibreurs de charge Google Cloud
Du côté back-end, la terminaison de QUIC est assurée par l'infrastructure Google Cloud Load balancing, qui utilise Les en-têtes dans les réponses pour prendre en charge QUIC. En général, pour chaque requête HTTP, le répartiteur de charge ajoute un en-tête alt-svc et c'est lui qui valide la prise en charge de 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 à ce domaine. Une fois que le répartiteur de charge termine QUIC, notre infrastructure envoie clairement cette action par HTTP2/TCP vers nos centres de données.
Performance : résultats
La performance délivrée est la principale raison de notre recherche du meilleur protocole. Pour commencer, nous avons créé une plateforme avec , afin de déterminer comment QUIC se comporterait dans différents profils de réseau. Pour tester QUIC dans des réseaux réels, nous avons réalisé des expériences en nous déplaçant dans New Delhi, tout en utilisant un trafic réseau émulé, très similaire aux appels HTTP dans l'application du passager.
Expérience 1
Inventaire pour l'expérience :
- dispositifs de test Android avec les stacks OkHttp et Cronet, afin de s'assurer que nous acheminons le trafic HTTPS par TCP et QUIC respectivement ;
- serveur d'émulation basé sur Java, qui envoie des en-têtes HTTPS uniformes dans les réponses et charge les appareils clients pour recevoir leurs requêtes ;
- proxies cloud, physiquement situés près de l'Inde, pour terminer les connexions TCP et QUIC. Alors que nous avons utilisé un proxy inverse pour terminer TCP, , il était difficile de trouver un proxy inverse open source pour QUIC. Nous avons construit notre propre proxy inverse pour QUIC, en utilisant la pile QUIC de Chromium et l'avons intégré dans Chromium comme open source.
Figure 6. L'équipement de test TCP contre QUIC était composé de dispositifs Android avec OkHttp et Cronet, des proxies cloud pour terminer les connexions et un serveur d'émulation.
Expérience 2
Lorsque Google a rendu QUIC disponible via , nous avons utilisé le même inventaire, mais avec une seule modification : au lieu de NGINX, nous avons pris les répartiteurs de charge de Google pour terminer les connexions TCP et QUIC des appareils, ainsi que pour diriger le trafic HTTPS vers le serveur d'émulation. Les répartiteurs de charge sont répartis à travers le monde, mais utilisent le serveur PoP le plus proche de l'appareil (merci à la géolocalisation).
Figure 7. Dans la deuxième expérience, nous avons voulu comparer la latence de terminaison entre TCP et QUIC : avec Google Cloud et avec notre proxy cloud.
Au final, nous avons eu plusieurs révélations :
- terminer via PoP a amélioré la performance TCP. Puisque les équilibres de charge terminent les connexions TCP plus près des utilisateurs et sont bien optimisés, cela donne des RTT plus faibles, ce qui améliore les performances TCP. Bien que cela ait eu moins d'impact sur QUIC, il a tout de même dépassé TCP en termes de réduction des latences de queue (de 10 à 30 pour cent).
- les queues sont affectées . Bien que notre proxy QUIC soit plus éloigné des dispositifs (avec un retard d'environ 50 ms de plus) que les équilibres de charge de Google, il a montré des performances similaires – une réduction de 15 % des latences contre 20 % pour le 99e percentile de TCP. Cela indique que la dernière milliaire est un goulet d'étranglement (bottleneck) dans la performance du réseau.
Figure 8. Les résultats des deux expériences montrent que QUIC surpasse significativement TCP.
Trafic en production
Inspirés par les expériences, nous avons intégré le support de QUIC dans nos applications Android et iOS. Nous avons effectué des tests A/B pour évaluer l'impact de QUIC dans les villes où Uber est présent. Globalement, nous avons observé une réduction significative des latences de queue à travers les régions et les opérateurs mobiles ainsi que les types de réseaux.
Les graphiques ci-dessous montrent les améliorations en pourcentage des queues (95e et 99e percentiles) par macro-régions et différents types de réseau – LTE, 3G, 2G.
Figure 9. Dans les tests en conditions réelles, QUIC a surpassé TCP en matière de latence.
Tout droit devant
Ceci n'est peut-être que le début – le déploiement de QUIC en production a offert d'incroyables possibilités d'améliorer les performances des applications tant dans les réseaux stables qu'instables, notamment :
Augmentation de la couverture
En analysant les performances du protocole sur le trafic réel, nous avons constaté qu'environ 80 % des sessions utilisaient avec succès QUIC pour tous des requêtes, tandis que 15 % des sessions utilisaient une combinaison de QUIC et TCP. Nous supposons que cette combinaison est due au fait que la bibliothèque Cronet revient à TCP en raison d'un délai d'expiration, car elle ne peut pas distinguer les réelles pannes UDP et les mauvaises conditions de réseau. Nous cherchons actuellement une solution à ce problème, alors que nous travaillons sur le déploiement futur de QUIC.
Optimisation de QUIC
Le trafic des applications mobiles est sensible aux délais, mais pas à la bande passante. De plus, nos applications sont principalement utilisées dans des réseaux cellulaires. D'après nos expériences, les délais en queue restent élevés, même avec l'utilisation de proxys pour terminer TCP et QUIC près des utilisateurs. Nous cherchons activement des moyens d'améliorer la gestion de la congestion et d'augmenter l'efficacité des algorithmes QUIC de récupération des pertes.
Avec ces améliorations et d'autres, nous prévoyons d'améliorer l'expérience utilisateur, quel que soit le réseau ou la région, rendant le transport de paquets pratique et transparent plus accessible à travers le monde.
Source : habr.com
