Rechtzeitigkeit in QUIC ohne Datagramme umsetzen
(quic.video)- Bei Live-Video und Gesprächen im Internet geht es nicht primär um „unzuverlässige Übertragung“, sondern darum, veraltete Daten zu verdrängen und die neuesten Daten rechtzeitig zu übertragen
- Wenn Router überlastete Pakete nicht verwerfen, sondern lange in Warteschlangen halten, entsteht Bufferbloat, was bei Echtzeitdiensten zu Verzögerungen führen kann, die schlimmer sind als Buffering
- Wer ein Protokoll direkt über UDP baut, muss Neuübertragungen, Congestion Control, Verschlüsselung, RTT-Schätzung, Pfadvalidierung, Flow Control usw. erneut implementieren; daher ist die Nutzung einer QUIC-Bibliothek sicherer
- Schon mit QUIC allein lässt sich durch die Kombination aus latenzbasierter Congestion Control, unabhängiger Stream-Aufteilung und Priorisierung Rechtzeitigkeit ohne Datagramme erreichen
- QUIC-, WebTransport- und MoQ-Standards unterstützen zwar Datagramme, doch statt ein neues Videoprotokoll erneut über UDP zu stapeln, ist es besser, sich am Media over QUIC-Ansatz zu orientieren
Das Ziel ist nicht „Unzuverlässigkeit“, sondern Rechtzeitigkeit
- Die Wahl zwischen TCP und UDP wird oft als Gegensatz zwischen „zuverlässiger Übertragung“ und „unzuverlässiger Übertragung“ erklärt, aber Anwendungen wollen nicht Unzuverlässigkeit an sich
- Bei Live-Video oder Gesprächen im Internet ist es wichtiger, dass die neuesten Daten zuerst ankommen, als dass alle alten Daten vollständig eintreffen
- In Echtzeitgesprächen will man weder einen Buffering-Spinner über Gesichtern sehen noch Audio von vor 5 Sekunden hören
- Die Live-Video-Branche und die Spieleindustrie nutzen für diese Art von Rechtzeitigkeit oft UDP-Datagramme statt TCP-Streams
Datagramme und Netzwerk-Warteschlangen
- Ein Datagramm ist ein Umschlag aus Nullen und Einsen, der von einer Quelladresse zu einer Zieladresse gesendet wird; als sichere Größe gelten im Allgemeinen 1200 Byte
- Datagramme können stillschweigend verloren gehen und auch in anderer Reihenfolge ankommen
- Auf der physischen Schicht werden Daten in analoge Signale umgewandelt und über das Medium übertragen; dabei können Serialisierung, Deserialisierung, Buffering, Queueing, Neuübertragung, Verwerfen, Beschädigung, Verzögerung, Neuordnung, Duplikation und Verlust auftreten
- Wenn zu viele Daten ins Netzwerk eingespeist werden, verwerfen Router Daten nicht an beliebigen Bitpositionen, sondern an Paketgrenzen
Bufferbloat und Congestion Control
- Wenn Router Pakete nicht sofort verwerfen, sondern in Warteschlangen aufstauen, entsteht Bufferbloat
- Bufferbloat kann alle Pakete um mehrere Sekunden verzögern und ist damit der Worst Case für Echtzeitübertragung
- Um Queueing zu vermeiden, muss man anhand des Feedbacks zu Paketankunftszeiten das Queueing im Router abschätzen, damit der Sender seine Sendemenge reduziert und die Queue leert
- Dieser Bereich gehört zur Congestion Control; Pakete mit unbegrenzter Rate zu senden, kann in einer Katastrophe enden
Was man sich aufhalst, wenn man direkt auf UDP aufbaut
- Wer mit UDP direkt ein Transportprotokoll baut, braucht mindestens die folgenden Funktionen
- Für ein besseres Protokoll kommen noch diese Funktionen hinzu
- Für höhere Reife muss man auch Betriebsumgebung und Deployment berücksichtigen
- Live-Video-Protokolle wie WebRTC, SRT, Sye und RIST sind Beispiele für Ansätze, die auf UDP aufbauen
- Daraus ergibt sich die Einschätzung, dass man besser eine QUIC-Bibliothek nutzt, als selbst ein neues Protokoll zu entwerfen
Rechtzeitigkeit mit QUIC-Streams herstellen
- Es gibt drei zentrale Wege, in QUIC Rechtzeitigkeit zu erreichen
- Buffer-Aufblähung vermeiden: Latenzbasierte Congestion Control wie BBR erkennt Queueing und reduziert die Sendemenge
- Das transport-wide-cc von WebRTC kann als Beispiel für einen besseren Ansatz gelten
- Stream-Aufteilung: Innerhalb jedes Streams sind Bytes geordnet und werden zuverlässig übertragen; Streams können atomare Einheiten wie Videoframes, Spiel-Updates, Chat-Nachrichten oder JSON-Blobs sein
- Stream-Priorisierung: Streams sind unabhängig und können unabhängig von ihrer Reihenfolge ankommen; dem QUIC-Stack kann mitgeteilt werden, wichtige Streams zuerst auszuliefern
- Streams mit niedriger Priorität können verhungern und lassen sich schließen, um Bandbreitenverschwendung zu vermeiden
- Dieser Ansatz ist der Kern von Media over QUIC
- Der Fire-and-Forget-Charakter von Datagrammen passt nur dann, wenn echte Echtzeitlatenz erforderlich ist; sonst können QUIC-Streams verwendet werden
Kompromisse und Ausnahmen rund um Datagramme
- QUIC und verwandte Standards enthalten auch Datagramm-Unterstützung
- QUIC bietet per Erweiterung Datagramm-Unterstützung
- WebTransport verlangt Datagramm-Unterstützung
- Die aktuelle MoQ-Version fügt Datagramm-Unterstützung hinzu
- Die nächste MoQ-Version wird Datagramm-Unterstützung verlangen
- Datagramm-Unterstützung kann aufgenommen werden, weil die Implementierung trivial ist und Experimente erlaubt
- OPUS hat eingebaute FEC-Unterstützung; damit ist es ein Beispiel dafür, dass MoQ das Senden jedes Audio-„frame“ als Datagramm unterstützen kann
- Das ältere Protokoll DNS kann als Ausnahme gelten, aber für neue Designs sei eine Richtung wie DNS over HTTPS vorzuziehen
- Das Fazit lautet: Statt ein neues Videoprotokoll erneut über UDP zu bauen, sollte man sich an Media over QUIC beteiligen
1 Kommentare
Meinungen auf Hacker News
In einer Umgebung wie NB-IoT etwa, in der die Round-Trip-Latenz im schlimmsten Fall 10 Sekunden beträgt, wird Round-Trip-Zeit für Handshake und MTU-Erkennung verschwendet; es wird weiter versucht, Daten zu übertragen, die nicht mehr nützlich sind; und wenn schlechtere Abdeckung die Latenz erhöht, interpretiert TCP das als paketverlustbedingte Überlastung und reduziert die Bandbreite
Außerdem können Load Balancer oder Middleboxes die Verbindung kappen nach dem Motto „seit 4 Sekunden keine Antwort, also ist sie wohl weg“, und weil TCP Pakete ohne Rücksicht auf die Datenstruktur aufteilt, ist es ebenfalls unschön, dass man sie erst interpretieren kann, wenn alles empfangen wurde
In manchen Fällen ist das nützlich, aber oft kann man das (n+1)-te Paket verwenden, auch wenn das n-te noch fehlt
Bei großen Dateiübertragungen kann man mit Erasure Coding 5 % Paketverlust automatisch behandeln oder Fountain Codes verwenden und so lange senden, bis der Empfänger sagt: „Ich habe alles“
Fountain Codes sind die Methode, mit der Weltraumsonden im tiefen All Daten senden, und die Latenz bis Jupiter oder Mars ist ziemlich erheblich
Erst wenn der TCP-Handshake abgeschlossen ist, kann der TLS-Handshake beginnen; QUIC bietet dagegen Unterstützung auf Protokollebene, um die TLS-Aushandlung im initialen Handshake abzuwickeln
Es wirkt zwar eleganter, Netzwerkprotokoll und Verschlüsselung lose kombinieren zu können, aber in einer Welt, in der inzwischen fast jede Übertragung verschlüsselt ist, scheint der praktische Vorteil größer zu sein, pro Verbindung eine Round-Trip-Zeit einzusparen
Im R&D-Bereich wurde ein neues System mit QUIC gebaut, das die meisten Probleme mit außer der Reihenfolge ankommenden Daten gelöst hat, aber Drittanbieter-Sensoren, die ohne Adapter direkt unterstützt werden müssen, können nur UDP; daher werden weiterhin für alles UDP-Datagramme verwendet
Der gebräuchlichere und bessere Ausdruck ist best-effort: UDP versucht die Zustellung von Datagrammen nach bestem Vermögen, nur können Datagramme eben verworfen werden
Das bedeutet nicht, dass UDP grundsätzlich nicht vertrauenswürdig wäre
https://en.wikipedia.org/wiki/Best-effort_delivery
Tatsächlich bedeutet es nicht, dass man bis zum Ende alles versucht, um eine Nachricht von A nach B zu schicken, sondern eher „wir haben es versucht“
Wenn ein Router auf dem Pfad überlastet ist oder durch ein Link-Flap vor dem schnellen Rerouting etwa 50 ms lang ein Blackhole entsteht, heißt es gewissermaßen: „Na ja, versucht haben wir es“
TCPs zuverlässige Zustellung dagegen versucht es mehrfach erneut und liefert der Anwendung einen korrekt geordneten Datenstream
reliable/unreliable mögen ebenfalls schlechte Begriffe sein, aber es ist schwer zu behaupten, best-effort sei besser
Nicht zuverlässige Systeme sind zu etwa 95 % großartig und auch gut für den rohen Durchsatz, aber die letzten 5 % machen oft einen sehr großen Unterschied
„Anstrengung“ bedeutet gewöhnlich ein gewisses Maß an Beharrlichkeit angesichts von Schwierigkeiten; ein Paket zu verwerfen, weil Ressourcen knapp werden, ist schwerlich Anstrengung zu nennen, geschweige denn best effort
„Best efforts“ als Rechts- und Geschäftssprache ist zwar schwächer als eine feste Zusage, bedeutet aber nicht, offen die Hände in den Schoß zu legen; die Verwendung in der Netzwerktechnik ist davon ziemlich verschieden
Unabhängig davon gewährleisten auch die Checksummen von UDP und TCP die Integrität nicht besonders gut, wenn ein Datagramm zugestellt wurde; sie sind nur etwas besser als Hardware
Allerdings erweckt best-effort den Eindruck, als würde etwas unternommen, um die Zustellung zu garantieren; tatsächlich werden Pakete, die merkwürdig aussehen oder Pech haben und auf einen vollen Buffer treffen, einfach verworfen
lossy gefällt mir, aber das gehört zu diesem Namensgebungsproblem aus „es gibt nur zwei schwierige Dinge“
Wenn Pakete ankommen müssen, nimmt man TCP; wenn es nicht groß darauf ankommt, nimmt man UDP
Das ist zwar eine vereinfachte Erklärung, aber best effort ist ein dummer Begriff, und darin steckt keine Anstrengung
Congestion Control ist sicher notwendig, aber darüber hinaus habe ich viele Zweifel
In einer Datagramm-zuerst-Welt hätte man mehrere Datenlinks sehr effizient bündeln oder problemlos über Netzwerkgrenzen hinweg roamen können, ohne die Verbindung zu unterbrechen
Viele Anwendungen können Frames, die außer der Reihenfolge ankommen, ohne zusätzliche Kosten verarbeiten und könnten deutlich schneller sein, wenn sie passend zum UDP-Modell geschrieben würden
Tatsächlich wird Software nicht automatisch zuverlässiger oder effizienter, nur weil man zu einer weniger zuverlässigen Transportmethode wechselt
Vielmehr nehmen die Fehlermodi und die Komplexität, mit denen das Team umgehen muss, erheblich zu
Wenn es irgendwo in der Verbindung jedoch einen engen Flaschenhals gibt, scheint es wenig sinnvoll, massenhaft Pakete zu erzeugen, die an diesem Engpass ohnehin verworfen werden
Websites, Audio und Video kommen im Allgemeinen nicht gut mit Frames zurecht, die in falscher Reihenfolge ankommen, und die meisten wollen nicht, dass Audio oder Video aussetzt
Einige Videospiele können fehlende Pakete ignorieren, aber solche Fälle sind bereits mit UDP geschrieben
Der Gedanke dahinter ist, dass diese Pakete nicht erneut übertragen werden und das daher eine wirksame Methode ist, überschüssigen Traffic zu reduzieren
Inzwischen gibt es Protokolle über UDP, die aggressiv erneut übertragen; ich frage mich, wie das die Lage verändert hat
Ich erinnere mich auch, dass QUIC vor einigen Jahren deswegen im Vergleich zu HTTP/1 und HTTP/2 Probleme mit Retransmissions hatte
Wenn sich im Artikel eine repräsentativere Formulierung findet, kann er wieder geändert werden
Das folgt der HN-Titelrichtlinie „Originaltitel verwenden, außer er ist irreführend oder Clickbait“: https://news.ycombinator.com/newsguidelines.html
Je nach Anwendung ist das sinnvoll
Wenn in einem Echtzeit-Multiplayer-Spiel zum Beispiel die Verarbeitung hinterherhinkt, sind die verzögerten Einträge nicht mehr wichtig, weil sich der Spielzustand bereits geändert hat
Auch bei High-Frequency-Trading-Anwendungen zählt in manchen Situationen nur die aktuellsten Marktdaten, nicht das, was vor 100 ms passiert ist
Der Artikel nennt auch Spiele und Live-Video als Beispiele, bei denen UDP passend ist
Er ist so aufgebaut, dass zunächst eine „gängige Vorstellung“ vorgestellt und danach widerlegt wird
Dazu gehören zum Beispiel lokale Discovery wie DHCP, SLAAC, UPnP, mDNS, tinc und BitTorrent, Broadcast wie Streaming im lokalen Netzwerk sowie Kapselung wie WireGuard, IPSec, OpenVPN und VLAN
Schon Buffering für Neuordnung, ganz zu schweigen von Retransmissions, erhöht die Latenz; daher ist es besser, Verluste mit Fehlerkorrektur oder Packet Loss Concealment in Kauf zu nehmen
UDP und TCP haben unterschiedliches Verhalten und unterschiedliche Trade-offs; man muss sie einfach verstehen, bevor man passend zum Anwendungsfall wählt
Dieses Gatekeeping nach dem Muster „Tu niemals X“ ist nicht nötig
Schon am Titel ist ziemlich klar, dass der Artikel kein Gatekeeping betreiben will, um UDP zu verbieten
Tatsächlich schlägt der Autor am Ende des Artikels die Nutzung von QUIC vor, das auf UDP basiert
Natürlich muss man sich dann um deutlich mehr Details selbst kümmern
Als Bonus ist es auch eine gute Möglichkeit, die Low-Level-Aspekte von Networking zu lernen