- Dans la vidéo en direct et les conversations sur Internet, l’important n’est pas la « livraison non fiable » en soi, mais d’évincer les données anciennes et de livrer les données les plus récentes à temps
- Si les routeurs n’abandonnent pas les paquets en cas de congestion et les laissent s’accumuler longtemps dans les files, cela provoque du bufferbloat, pouvant entraîner dans les services temps réel une latence pire que le buffering
- Si l’on construit un protocole directement au-dessus d’UDP, il faut réimplémenter les retransmissions, le contrôle de congestion, le chiffrement, l’estimation du RTT, la validation de chemin, le contrôle de flux, etc. ; il est donc plus sûr d’utiliser une bibliothèque QUIC
- Avec QUIC seul, on peut créer de la ponctualité sans datagrammes en combinant contrôle de congestion fondé sur la latence, découpage en flux indépendants et priorisation
- Les standards QUIC, WebTransport et MoQ intègrent la prise en charge des datagrammes, mais la conclusion est qu’il vaut mieux s’aligner sur l’approche Media over QUIC que reconstruire un nouveau protocole vidéo au-dessus d’UDP
L’objectif n’est pas le « manque de fiabilité », mais la ponctualité
- Le choix entre TCP et UDP est souvent présenté comme une opposition entre « livraison fiable » et « livraison non fiable », mais ce que veut l’application n’est pas le manque de fiabilité en soi
- Dans la vidéo en direct ou les conversations sur Internet, il est plus important que les données les plus récentes arrivent d’abord que de recevoir toutes les données anciennes
- Dans une conversation en temps réel, il faut éviter de voir un indicateur de buffering sur le visage de l’interlocuteur ou d’entendre l’audio d’il y a 5 secondes
- Les secteurs de la vidéo en direct et du jeu vidéo utilisent souvent des datagrammes UDP plutôt que des flux TCP pour obtenir cette ponctualité
Datagrammes et files réseau
- Un datagramme est une enveloppe de 0 et de 1 envoyée d’une adresse source vers une adresse de destination ; en général, 1200 octets sont considérés comme une taille sûre
- Un datagramme peut être perdu silencieusement, ou arriver dans un ordre différent
- Au niveau physique, les données sont converties en signaux analogiques et traversent le support ; sérialisation, désérialisation, buffering, mise en file, retransmission, abandon, corruption, retard, réordonnancement, duplication et perte peuvent se produire
- Quand trop de données entrent dans le réseau, les routeurs ne jettent pas des bits arbitraires, mais abandonnent les données aux frontières des paquets
Bufferbloat et contrôle de congestion
- Si un routeur n’abandonne pas immédiatement les paquets et les accumule dans une file, du bufferbloat apparaît
- Le bufferbloat peut retarder tous les paquets de plusieurs secondes, créant la pire situation pour une livraison en temps réel
- Pour éviter la mise en file, il faut estimer la file du routeur à partir du retour sur les temps d’arrivée des paquets, puis réduire le débit d’envoi afin de vider la file
- Ce domaine relève du contrôle de congestion, et envoyer des paquets à vitesse illimitée peut mener à la catastrophe
Les fonctionnalités à assumer quand on construit directement sur UDP
- Pour créer un protocole de transport en utilisant directement UDP, il faut au minimum les fonctionnalités suivantes
- Pour bâtir un meilleur protocole, il faut aussi les fonctionnalités suivantes
- Pour atteindre un bon niveau de maturité, il faut aussi tenir compte de l’environnement d’exploitation et du déploiement
- WebRTC, SRT, Sye et RIST sont des exemples de protocoles vidéo en direct construits au-dessus d’UDP
- Cela conduit à juger préférable d’utiliser une bibliothèque QUIC plutôt que de créer directement un nouveau protocole
Créer de la ponctualité avec les flux QUIC
- Dans QUIC, on peut résumer les moyens d’obtenir la ponctualité en trois approches
- Éviter le gonflement des buffers : un contrôle de congestion fondé sur la latence, comme BBR, détecte la mise en file et réduit le volume envoyé
- Le transport-wide-cc de WebRTC peut être vu comme un exemple de meilleure approche
- Découpage en flux : les octets à l’intérieur de chaque flux sont ordonnés et livrés de manière fiable, et un flux peut représenter une unité atomique comme une image vidéo, une mise à jour de jeu, un message de chat ou un blob JSON
- Priorisation des flux : les flux sont indépendants, peuvent arriver sans rapport avec leur ordre, et l’on peut indiquer à la pile QUIC de livrer d’abord les flux importants
- Les flux de faible priorité peuvent être affamés et, pour éviter de gaspiller de la bande passante, ils peuvent être fermés
- Cette approche est au cœur de Media over QUIC
- Le caractère fire-and-forget des datagrammes ne convient que lorsqu’une latence temps réel est nécessaire ; dans les autres cas, on peut utiliser les flux QUIC
Compromis et exceptions autour des datagrammes
- QUIC et les standards associés incluent aussi la prise en charge des datagrammes
- QUIC fournit la prise en charge des datagrammes via une extension
- WebTransport exige la prise en charge des datagrammes
- Les versions récentes de MoQ ajoutent la prise en charge des datagrammes
- La prochaine version de MoQ devrait exiger la prise en charge des datagrammes
- La prise en charge des datagrammes peut être incluse parce qu’elle est triviale à implémenter et permet l’expérimentation
- OPUS intègre la prise en charge de la FEC, ce qui en fait un exemple où MoQ prend en charge l’envoi de chaque « frame » audio sous forme de datagramme
- L’ancien protocole DNS peut être considéré comme une exception, mais pour les nouveaux designs, il est préférable de suivre une direction comme DNS over HTTPS
- La conclusion est qu’il vaut mieux participer à Media over QUIC que recréer un nouveau protocole vidéo au-dessus d’UDP
1 commentaires
Avis sur Hacker News
Par exemple, dans un environnement comme le NB-IoT, où la latence aller-retour peut atteindre 10 secondes dans le pire des cas, du temps aller-retour est gaspillé dans le handshake et la découverte du MTU ; il continue aussi à tenter d’envoyer des données qui ne servent plus à rien, et si la couverture se dégrade et que la latence augmente, TCP interprète cela comme une perte de paquets due à la congestion et réduit la bande passante
De plus, un load balancer ou une middlebox peut couper la connexion en se disant « pas de réponse depuis 4 secondes, elle a dû disparaître », et comme TCP découpe les paquets sans tenir compte de la structure des données, on ne peut pas les interpréter avant d’avoir tout reçu, ce qui est également regrettable
C’est utile dans certains cas, mais il y a beaucoup de situations où l’on peut exploiter n+1 même si n n’est pas encore là
Pour les gros transferts de fichiers, on peut gérer automatiquement 5 % de pertes de paquets avec des codes d’effacement, ou utiliser un fountain code et envoyer jusqu’à ce que le récepteur dise « j’ai tout reçu »
Les fountain codes sont la manière dont les sondes d’exploration de l’espace profond envoient des données, et la latence jusqu’à Jupiter ou Mars est assez sérieuse
Il faut que le handshake TCP soit terminé pour pouvoir lancer le handshake TLS, mais QUIC dispose d’un support au niveau du protocole pour gérer la négociation TLS dans le handshake initial
Pouvoir combiner de manière lâche un protocole réseau et le chiffrement paraît plus élégant, mais dans un monde où presque tous les transports sont désormais chiffrés, l’avantage pratique de gagner un aller-retour par connexion semble plus important
Côté R&D, nous avons créé un nouveau système utilisant QUIC, et il a résolu la plupart des problèmes d’arrivée dans le désordre, mais des capteurs tiers devant être pris en charge directement, sans adaptateur, ne savent faire que de l’UDP ; on utilise donc toujours des datagrammes UDP pour tout
L’expression la plus courante et la meilleure est best-effort : UDP tente de livrer les datagrammes au mieux, mais ceux-ci peuvent simplement être abandonnés
Cela ne signifie pas pour autant qu’UDP est intrinsèquement indigne de confiance
https://en.wikipedia.org/wiki/Best-effort_delivery
En pratique, cela ne veut pas dire qu’on s’acharne jusqu’au bout pour envoyer un message de A vers B, mais plutôt « on a essayé »
Si un routeur sur le chemin est congestionné, ou qu’un link flap crée un trou noir d’environ 50 ms avant un reroutage rapide, cela revient à dire « bon, on a tenté »
À l’inverse, la livraison fiable de TCP réessaie plusieurs fois et fournit à l’application un flux de données dans le bon ordre
reliable/unreliable peuvent aussi être de mauvais termes, mais il est difficile de considérer best-effort comme meilleur
Les systèmes non fiables fonctionnent très bien dans environ 95 % des cas et sont bons pour le débit brut, mais les 5 % restants font souvent une énorme différence
« Effort » implique généralement une certaine persévérance face à la difficulté ; jeter un paquet parce qu’il y a un problème de ressources mérite difficilement ce nom, et encore moins best effort
Dans le vocabulaire juridique et commercial, « best efforts » est moins fort qu’un engagement ferme, mais ce n’est pas non plus baisser ouvertement les bras ; l’usage en réseau en est assez différent
Par ailleurs, les checksums d’UDP et de TCP ne garantissent pas très bien l’intégrité lorsqu’un datagramme est livré, et ne font guère mieux que le matériel
Cela dit, best-effort donne l’impression qu’un effort est fait pour garantir la livraison, alors qu’en réalité un paquet jugé étrange ou ayant la malchance de tomber sur un buffer plein est simplement jeté
J’aime bien lossy, mais c’est un problème de nommage, qui entre dans la catégorie « il n’y a que deux problèmes difficiles »
Si le paquet doit arriver, utilisez TCP ; si ce n’est pas très important, utilisez UDP
C’est une explication simplifiée, mais best effort est un terme idiot : il n’y a aucun effort là-dedans
Le contrôle de congestion est clairement nécessaire, mais pour le reste, beaucoup de choses me laissent sceptique
Dans un monde datagramme d’abord, on aurait pu agréger plusieurs liaisons de données de manière très efficace, ou se déplacer entre des frontières réseau sans couper la connexion, sans problème
Beaucoup d’applications peuvent traiter des trames arrivées dans le désordre sans coût supplémentaire et pourraient être beaucoup plus rapides si elles étaient écrites selon le modèle UDP
En réalité, passer à un mode de transport moins fiable ne rend pas automatiquement les logiciels plus fiables ni plus efficaces
Au contraire, cela augmente fortement les modes de défaillance et la complexité que l’équipe doit gérer
Cela dit, s’il y a un goulot d’étranglement quelque part dans la connexion, produire énormément de paquets qui seront de toute façon jetés à ce goulot n’a pas l’air très utile
Les sites web, l’audio et la vidéo s’accommodent généralement mal de frames arrivant dans le désordre, et la plupart des gens ne veulent pas que l’audio ou la vidéo se coupe
Certains jeux vidéo peuvent ignorer les paquets manquants, mais dans ce cas ils sont déjà écrits en UDP
L’idée étant que, comme ces paquets ne seront pas retransmis, c’est une manière efficace de réduire le trafic excédentaire
Maintenant qu’il existe des protocoles au-dessus d’UDP qui retransmettent de manière agressive, je me demande comment cela a changé la situation
Je me souviens aussi que, il y a quelques années, QUIC avait pour cette raison des problèmes de retransmission par rapport à HTTP/1 et HTTP/2
Si l’on trouve dans l’article une formulation plus représentative, on peut le rechanger
C’est conforme à la règle de titre de HN : « utiliser le titre original, sauf s’il est trompeur ou racoleur » : https://news.ycombinator.com/newsguidelines.html
Selon l’application, c’est pertinent
Par exemple, dans un jeu multijoueur en temps réel, si le traitement prend du retard, les éléments en retard n’ont plus d’importance parce que l’état du jeu a déjà changé
Dans certaines situations, les applications de trading haute fréquence ne s’intéressent elles aussi qu’aux données de marché les plus récentes, pas à ce qui s’est passé il y a 100 ms
L’article cite aussi les jeux et la vidéo en direct comme exemples où UDP est adapté
Il commence par présenter une « idée reçue », puis la réfute
Par exemple : DHCP, SLAAC, UPnP, mDNS, tinc, la découverte locale comme BitTorrent, le broadcast comme le streaming sur réseau local, et l’encapsulation comme WireGuard, IPSec, OpenVPN ou les VLAN
Les retransmissions, et même le simple buffering pour remettre les paquets dans l’ordre, augmentent la latence ; mieux vaut donc accepter les pertes avec de la correction d’erreurs ou de la dissimulation de perte de paquets
UDP et TCP ont des comportements et des compromis différents ; tout ce qu’il faut, c’est les comprendre avant de choisir en fonction du cas d’usage
Pas besoin de faire du gatekeeping façon « ne faites jamais X »
Rien qu’avec le titre, il est assez clair que l’article ne cherche pas à faire du gatekeeping pour empêcher d’utiliser UDP
En fait, à la fin, l’auteur propose d’utiliser QUIC, qui est basé sur UDP
Bien sûr, il faut alors gérer soi-même beaucoup plus de détails
En bonus, c’est aussi une bonne manière d’apprendre les aspects bas niveau du réseau