TCP BBR: un moyen rapide et facile d'accélérer le chargement des pages. Rapport Yandex

Les protocoles modernes au niveau des applications utilisent le multiplexage pour accélérer la transmission de données, ce qui augmente les exigences de fiabilité des canaux. À la conférence YaTalks Alexander Gryanko phasmadit comment nous accélérons le chargement des pages sur les canaux avec une perte de paquets élevée en utilisant les protocoles HTTP / 2 et TCP BBR comme exemple.



- Salut. Je suis Sasha, je travaille chez Yandex, depuis trois ans je développe un load balancer L7. Je vais vous parler d'un moyen rapide et facile d'accélérer votre réseau. Nous allons commencer au septième niveau, HTTP, et descendre au quatrième niveau, TCP. Aujourd'hui, nous ne parlerons que de ces deux niveaux et nous y reviendrons plus en détail.



Au cours des huit dernières années, j'ai fait plus de développement backend, et très probablement mes connaissances sont restées au niveau d'AngularJS dans les premières versions. Vous savez probablement mieux que moi comment tout cela fonctionne. Vous avez déjà tout optimisé, tout compressé, et ici je ne peux rien vous conseiller.



Mais je peux vous conseiller sur la façon d'accélérer votre réseau en optimisant le serveur lui-même, le système d'exploitation lui-même.







Pour accélérer quelque chose, vous avez besoin de métriques. Dans ce cas, nous avons utilisé ce qui suit: le temps moyen jusqu'au premier octet nous montre à quelle vitesse la couche TCP est, et la deuxième métrique est le temps pour recevoir du HTML à partir du premier octet. Nous avons expérimenté, mesuré nos métriques et, après avoir activé BBR, notre accélération était d'environ dix pour cent.







Pour comprendre ce qu'est dix pour cent, nous nous tournons vers la valeur absolue, qui est de 66 millisecondes. Si vous accédez à votre jeu multijoueur en ligne préféré, le ping vers les serveurs d'Europe de l'Ouest durera environ 60 à 70 millisecondes.



Comment le faire rapidement



Tous nos serveurs sont gérés à l'aide de protocoles de contrôle à distance, dans ce cas SSH. Si vous n’avez pas encore rencontré SSH, vous pouvez demander à votre administrateur système de configurer votre serveur. Je vais vous dire comment le convaincre de faire cela.







Qu'est-ce que BBR? C'est l'un des algorithmes qui nous permet de contrôler la manière dont les paquets sont acheminés vers le réseau. Et il est configuré avec les deux paramètres suivants. La première consiste à définir le planificateur de paquets sur FQ, puis je vous expliquerai pourquoi vous devriez utiliser FQ. Le second est l'inclusion du contrôle de congestion lui-même, c'est-à-dire le BBR lui-même.



Il semble que c'est là que nous pourrions en finir. Mais en fait, il existe de nombreux pièges et il est fort probable que votre administrateur système n'activera pas uniquement BBR sur le serveur. Par conséquent, nous irons plus loin.



HTTP / 2 et multiplexage



Nous commencerons au niveau 7, qui est HTTP, et descendrons lentement pour revoir nos protocoles.







Nous allons commencer par nos navigateurs avec lesquels nous interagissons tous les jours. Nous voyons la console des développeurs Web. La console a un champ intéressant pour nous - protocole.



Dans notre cas, les protocoles sont HTTP / 1 et HTTP / 2. Il existe également le protocole HTTP / 3, basé sur le protocole QUIC de Google. Mais aujourd'hui, nous n'y reviendrons pas, car il est en cours de développement, pas encore pleinement approuvé. Revenons à HTTP / 1.







Sur la diapositive, nous voyons l'utilitaire Wireshark, qui nous permet d'analyser nos paquets, la façon dont nous interagissons avec le réseau. Nous voyons qu'un champ est surligné en vert. Ceci est notre requête HTTP. Ci-dessous, nous pouvons voir les octets, comment ils seront présentés sur le réseau.







À quoi ressemble HTTP / 1 dans la vraie vie? C'est un protocole assez simple. Il est entièrement basé sur du texte, c'est-à-dire que nous écrivons simplement le texte et l'envoyons au réseau. Nos caractères sont encodés avec des valeurs hexadécimales spéciales. Sur la droite se trouve une table ASCII, un petit morceau pour vous permettre de naviguer.



Nous avons la première partie sous la forme d'en-têtes, qui est séparée par les caractères «\ r \ n \ r \ n» de notre corps. Nous demandons simplement une ressource régulière ici avec la méthode GET, donc cette requête n'aura pas de corps. Et nous voyons que les octets sont approximativement similaires à ce qui est dans la table ASCII. Nous demandons une sorte de JS, une sorte de ressource. Il existe également un en-tête Host indiquant le domaine avec lequel nous travaillons actuellement. Et - un ensemble supplémentaire d'en-têtes. Ils peuvent être personnalisés, vous pouvez en utiliser.







HTTP / 2 est un protocole plus complexe. Il est binaire et la plus petite unité d'échange d'informations est constituée de trames. Il existe de nombreux cas particuliers, des types particuliers de ces cadres. Vous pouvez voir sur la diapositive qu'ils sont mis en évidence.







On peut également observer sur la première ligne que deux trames peuvent tenir dans un même paquet à la fois. Nous ne nous attarderons pas sur les cadres qui existent, il y en a pas mal. Dans ce cas, nous nous intéresserons au cadre des en-têtes, car il nous permet simplement de demander des ressources. J'ai été un peu impliqué dans le développement de Wireshark, contribuant à l'améliorer dans ce domaine.



Nous pouvons voir qu'il y a une demande d'obtention. Nous voyons qu'au milieu il y a une représentation textuelle de cette demande d'obtention. Mais dans la colonne de droite, nous ne voyons qu'un seul octet alloué, et ce sera cette méthode get. Ensuite, je vais expliquer pourquoi cela se produit.



Ensuite, nous avons l'en-tête de chemin, qui indique le chemin vers la ressource, vers notre JS, que nous demanderons. Et il y a un ensemble d'en-têtes supplémentaires qui seront également présents dans notre demande.



Alors pourquoi nos octets sur le réseau ne sont-ils pas les mêmes que la façon dont tout cela est dessiné dans notre image? Le fait est que Wireshark nous montre le résultat final, comment il a tout décodé. Et sur le réseau, ces octets, ces en-têtes, seront compressés avec un format HPACK spécial. Il est préférable de se familiariser avec plus de détails sur Internet. Cherchez des informations, elles sont bien documentées.



Revenons à nos bouchées. Il existe un champ spécial - l'identificateur de contenu. Il indique la ressource avec laquelle ces cadres travaillent actuellement. Dans ce cas, nous avons envoyé la première trame, les données reçues. Lorsque le serveur nous donne les octets de contenu eux-mêmes, la trame de données sera déjà utilisée.







Nos protocoles HTTP / 1 et HTTP / 2 sont très différents. Nous avons déjà parlé du fait que HTTP / 1 est un protocole de texte et HTTP / 2 est un protocole binaire, c'est-à-dire qu'il fonctionne avec des cadres.



HTTP / 1 dans le cas d'une requête sous la forme d'une connexion unique renverra un résultat inconnu, en fonction de l'implémentation de la façon dont les développeurs du serveur Web l'ont écrit. Autrement dit, si nous faisons deux demandes dans une connexion, il est fort probable qu'une réponse à la première ou à la deuxième demande soit renvoyée. Pour ce faire, afin de charger des ressources en parallèle, le navigateur établit plusieurs connexions, généralement environ six, et charge les ressources en parallèle.



HTTP / 2, à son tour, utilise une seule connexion. Autrement dit, il définit la connexion et à l'intérieur, il charge toutes les données nécessaires via des cadres. Cette technique consistant à regrouper plusieurs ressources en une seule connexion est appelée multiplexage.



Il ressort clairement du fonctionnement de nos connexions: en cas de perte de paquets dans l'une des connexions, HTTP / 1 fonctionnera mieux. Très probablement, nous ne toucherons pas aux autres connexions, elles continueront à se charger à la même vitesse. Et dans le cas de HTTP / 2, si notre paquet est perdu, le chargement de toutes les ressources commence à ralentir.







Il semble que HTTP / 2 soit pire, il est également sensible à la perte de paquets. En fait, lorsque nous créons chacune de ces six connexions, nous effectuons l'opération suivante.



Le client et le serveur établissent en quelque sorte une connexion fiable, une connexion TCP. Nous envoyons deux paquets du client au serveur, et un paquet est envoyé du côté serveur au client. Ainsi, nous semblons dire que nous sommes prêts à transférer des données. Ceci, bien sûr, crée des frais généraux, nous pouvons le faire pendant longtemps.







Il existe également un cryptage. Si vous regardez votre navigateur maintenant, vous verrez probablement une icône de cadenas. Beaucoup de gens l'appellent SSL, mais ce n'est pas vraiment SSL. C'est TLS. SSL est obsolète depuis longtemps, n'est pratiquement plus pris en charge et devrait être abandonné.



TLS a également l'échange de paquets. Autrement dit, nous, tout comme dans le cas d'une poignée de main TCP, définissons un certain état, après quoi nous pouvons continuer à travailler. À ce stade, nous pouvons également faire de l'optimisation, mais les navigateurs ne prennent pas encore en charge les choses que nous avons déjà activées du côté serveur. Nous attendrons que tout le monde l'allume.







Il était une fois, HTTP / 1 a tenté de résoudre le problème du chargement simultané des ressources. La RFC l'a. Et il était une fois le pipeline. En raison de la complexité de la mise en œuvre, Internet Explorer ne le prend pas en charge, contrairement à Firefox et Chrome, mais le support a été abandonné au fil du temps.







Chacune de nos six connexions que nous avons déjà créées, en fait, ne se fermera pas. Autrement dit, ils continueront à fonctionner de la même manière qu'avant. Pour cela, une technique telle que Keep-Alive est utilisée. Autrement dit, nous créons une connexion fiable à un serveur spécifique et continuons à travailler.



Au niveau HTTP, cela est contrôlé par l'en-tête. Dans ce cas, il s'agit de connexion. Et au niveau TCP, nous utiliserons déjà le système d'exploitation lui-même, il décidera pour nous quoi faire.







Il existe également d'autres problèmes avec HTTP / 2. Dans HTTP / 2, nous pouvons hiérarchiser les paquets et envoyer plus de données nécessaires plus rapidement. Dans ce cas, lorsque nous essayons d'envoyer beaucoup de données à la fois, la mémoire tampon sur le serveur peut déborder. Ensuite, les paquets de priorité plus élevée ralentiront simplement et iront à la fin de la file d'attente.



Une perte de paquets est observée. Ils ralentissent notre chargement, et ce blocage est appelé blocage de tête de ligne.



Comment TCP résout les problèmes de perte de paquets



Nous allons maintenant parler de TCP, c'est-à-dire de notre quatrième couche. Dans les dix prochaines minutes, je couvrirai le fonctionnement de TCP.







Lors de notre visite, nous demandons à quelqu'un de passer le sel. Lorsqu'une personne nous donne du sel, nous confirmons que le sel nous est parvenu. Dans ce cas, nous prenons également un segment, le transmettons et attendons la confirmation. Nous transmettons à nouveau. Et s'il y a une perte, nous transmettons ce segment et, par conséquent, il nous est livré. Cette technique d'envoi d'un segment est appelée Stop and wait.



Mais nos réseaux se sont considérablement accélérés au cours des 30 dernières années. Certains d'entre vous se souviennent peut-être de l'accès commuté, d'Internet par mégaoctets. À présent, vous pourrez peut-être déjà vous connecter à Internet gigabit à la maison.



De plus, dans ce cas, nous pouvons commencer à envoyer plusieurs colis à la fois. Dans notre exemple, il y en a trois. Nous envoyons la fenêtre sous forme de trois paquets et attendons qu'ils soient tous confirmés.



En cas de perte de paquets, nous pouvons commencer à réexpédier tous les paquets, à partir de notre première perte. Cette technique s'appelle Go-Back N. Sinon, nous pouvons commencer à suivre tous les paquets et ne transmettre que ceux qui ont été perdus. Cette technique est appelée répétition sélective. C'est plus cher côté serveur. Lors de la préparation des diapositives, il a fallu beaucoup de temps pour savoir comment les présenter. J'étais moi-même confus là-dedans et je suis donc venu avec une telle analogie.







Il existe des tuyaux connus de nous tous à travers lesquels l'eau coule. Les tuyaux ont des diamètres différents, quelque part ils peuvent être plus minces, et dans ce cas, le point le plus étroit sera juste avec notre débit maximal. Nous ne pourrons pas verser plus d'eau que ne le permet ce goulot d'étranglement.



Nous allons essayer de tirer des balles de gauche à droite. Sur le côté droit, on confirmera que les balles ont volé. Nous commençons à envoyer un flot de balles. Jetons un coup d'œil à sa coupe. Maintenant, les balles volent dans une direction, elles sont confirmées, et le nombre de nos balles augmente de façon exponentielle. À un moment donné, le volume des balles devient si grand qu'elles ralentissent et les pertes commencent. Après la perte, nous ralentissons un peu, réduisons notre fenêtre de moitié. Ensuite, nous essayons de comprendre ce qui nous est arrivé. La première étape est appelée TCP Slow Start.







Lorsque nous avons fermé la fenêtre deux fois, nous pouvons rétablir la connexion et demander aux gars de nous renvoyer nos balles. Ils nous crient que nous devons envoyer les balles, nous leur répondons - voici vos balles. Cette phase est appelée Fast Recovery et Fast Retransmit.







Lorsque nous avons réalisé que tout allait bien pour nous, nous commençons à augmenter progressivement le nombre de balles envoyées, à partir de cette fenêtre effondrée. Cette phase est appelée évitement de la congestion. Autrement dit, nous essayons d'éviter de perdre nos paquets.



La phase où notre fenêtre s'effondre deux fois s'appelle la diminution multiplicative. Et la phase lente d'augmentation du nombre de boules s'appelle Augmentation additive.



Lorsque notre système d'évitement de congestion perd à nouveau des paquets, nous pouvons passer à l'étape suivante. Mais pour le moment, nous nous intéressons davantage à l'image même de ce graphique. Nous voyons une telle scie, et cette scie nous sera utile à plusieurs reprises. Rappelez-vous à quoi cela ressemble.







Nous reviendrons sur les problèmes des protocoles TCP conventionnels. Par analogie avec une pipe, on verse des sacs. Puisqu'il y a d'autres utilisateurs sur Internet en plus de nous, ils commencent également à verser des paquets dans le tuyau. À un moment donné, les tampons de nos routeurs peuvent déborder et créer des problèmes pour nous d'envoyer des paquets.



Il existe également un problème de perte de paquets sur les réseaux sans fil. Très probablement, votre ordinateur portable n'a pas de port Ethernet et vous regardez une conversation via Wi-Fi. La perte de paquets sur les réseaux Wi-Fi et mobiles n'est pas causée par le routeur lui-même, mais par des interférences radio. Cette métrique ne nous sera pas très utile.



Différence de TCP BBR par rapport aux autres algorithmes







Ici, nous arrivons à BBR. Cela signifie Bottleneck Bandwidth et Round Trip Time, ce sont des mesures de la bande passante lorsque nous n'obstruons pas complètement notre canal, et le temps de trajet du paquet de nous au serveur et retour.



Lorsque nous envoyons des données, l'état idéal dans lequel les paquets sont dans un état stable, volent et n'ont pas encore été acquittés est appelé le produit de délai de bande passante. Nous pouvons augmenter le BDP en utilisant des tampons de périphériques réseau. Lorsque ce tampon est dépassé, les pertes commencent.



Et les algorithmes TCP habituels ne fonctionnent que sur le côté droit du graphique, c'est-à-dire là où des pertes se produisent - nous versons tellement de paquets que les pertes sont inévitables. Les paquets ralentissent et nous commençons à réduire la fenêtre.



BBR, quant à lui, fonctionne sur un principe différent, proche de notre pipe. Nous versons juste autant de sacs que nous pouvons sauter. Dans la phase de démarrage, c'est-à-dire au tout début, nous remplissons les sacs jusqu'à ce que la congestion commence.



Et parfois, la perte de paquets est possible. Mais BBR essaie d'éviter ce moment. Lorsque nous avons rempli notre pipe, nous commençons à reculer. Cette phase est appelée drain.







Nous revenons à notre connexion stable, où elle sera complètement remplie, mais en même temps, nous n'utiliserons pas de tampons supplémentaires, de réservoirs supplémentaires. À partir de cette position, BBR continue de fonctionner.



De temps en temps, nous examinerons ce qui se passe avec notre réseau. Nous suivons presque tous les colis qui nous sont retournés. Lorsque les paquets nous sont retournés, nous commençons à essayer d'accélérer un peu le nombre de paquets, d'accélérer les paquets eux-mêmes en les envoyant sur le réseau.







Et si nous n'avons aucun problème, nous pouvons rester à cette valeur. Autrement dit, continuer à travailler au rythme qui nous convient. Si, cependant, il y avait des pertes, nous pouvons revenir en arrière.



Lorsque nous avons reçu la confirmation, vu que la vitesse s'est améliorée, nous pouvons attendre un peu, regarder l'intervalle de dix secondes. Et si dans cet intervalle nous voyons que la vitesse d'envoi des paquets augmente et que les paquets sont confirmés plus rapidement, alors nous pouvons entrer dans la phase de sonde RTT et vérifier si tout va encore mieux.







Ces phases alternent, c'est-à-dire que nous vérifierons constamment ce que nous avons avec le réseau.



L'algorithme BBR n'est plus basé sur la perte de paquets, mais sur la largeur du canal et le temps de parcours des paquets.







En fait, il est immunisé contre la perte de paquets. Il n'y réagit pratiquement pas, et à cause de cela, nous avons des problèmes. Google a promis que ces problèmes seraient résolus dans BBR v2.



Nous avons examiné nos phases, et devant nous se trouve à nouveau le peigne, que j'ai déjà montré. Les protocoles TCP normaux sont surlignés en rouge. Alors il ramasse, ramasse, ralentit et perd à nouveau des colis. Et BBR fixe le rythme dont il a besoin, avec lequel il travaillera tout le temps, et vérifie constamment notre réseau pour voir s'il s'est un peu amélioré. Et cela peut s'accélérer.



Nos métriques sont constamment mises à jour, nous suivons chaque confirmation du client et vérifions si notre réseau s'est accéléré ou non.



Comment ce taux d'envoi de paquets est-il contrôlé? Nous contrôlons le rythme d'envoi en utilisant la technique de stimulation. Il est implémenté dans le planificateur que j'ai mentionné plus tôt. C'est le planificateur FQ. Il est également implémenté dans le noyau lui-même, mais j'en parlerai plus tard.



Nous essayons, comme dans un tuyau, de verser plus de données, et en même temps de ne pas ralentir, de ne pas perdre nos paquets. Mais BBR n'est pas si simple. Très probablement, vous vivez dans des conteneurs ou utilisez plusieurs serveurs pour les bases de données - peut-être pour les images.







Et tous ces serveurs interagissent les uns avec les autres. Il y a TCP normal activé, pas BBR. Et quand vous avez la scie, que nous avons déjà vue, lorsque la fenêtre commence à s'effondrer, alors peut-être que BBR commencera à tâtons que la fenêtre s'effondre et augmentera le taux d'envoi de paquets. Ainsi, il évincera le TCP ordinaire de notre réseau, dominera.



Si le réseau est très mauvais, d'autres problèmes sont possibles. Le TCP ordinaire ne fonctionnera pas du tout, et comme BBR est pratiquement insensible à la perte de paquets, il continuera à fonctionner à un certain rythme.



Nous pouvons résoudre ce problème avec les centres de données avec l'option TCP_CONGESTION. Il est exposé pour chaque socket, pour chaque connexion. Maintenant, pour autant que je sache, cette option n'est pas implémentée dans presque tous les serveurs Web. Et notre équilibreur L7 le prend en charge. Mais revenons à notre rythme. Si vous travaillez avec des noyaux plus anciens, il y avait un bogue dans l'implémentation de la stimulation dans les noyaux antérieurs à la version 4.20. Dans ce cas, il vaut la peine d'utiliser le planificateur FQ.







Maintenant que vous savez comment fonctionne TCP, vous pouvez aller voir votre administrateur système et lui dire pourquoi vous devriez activer BBR.



Revenons à nos dix pour cent. D'où peuvent-ils venir? Les réseaux d'opérateurs sont désormais très vastes. Tout n'est qu'une question d'argent. Vous pouvez créer des chaînes pour 100, 200 térabits et sauter une énorme quantité de vidéos 4K, par exemple. Mais votre client sera toujours au point final.



Et très probablement, ce dernier kilomètre vers le client sera la source de problèmes. Tous nos Wi-Fi et LTE perdront des forfaits. Nous verrons des ralentissements lors de l'utilisation de TCP standard. BBR résout ce problème. Vous pouvez l'activer avec seulement les deux commandes que j'ai indiquées. Merci à tous.



All Articles