Seit mehr als 20 Jahren besuchen wir Webseiten über das HTTP-Protokoll. Die meisten Benutzer machen sich überhaupt keine Gedanken darüber, was es ist und wie es funktioniert. Andere wissen, dass es irgendwo unter HTTP TLS gibt, und darunter TCP, und darunter IP und so weiter. Und die dritten – die Häretiker – glauben, dass TCP altmodisch ist und etwas Schnelleren, Zuverlässigeres und Sichereres wollen. Doch in ihren Versuchen, ein neues, ideales Protokoll zu erfinden, sind sie zu den Technologien der 80er Jahre zurückgekehrt und versuchen, auf deren Basis ihre wunderbare neue Welt aufzubauen.

Ein wenig Geschichte: HTTP/1.1
Im Jahr 1997 erhielt das Protokoll für den Austausch von Textinformationen HTTP Version 1.1 sein RFC. Zu diesem Zeitpunkt wurde das Protokoll bereits seit mehreren Jahren von Browsern verwendet, und der neue Standard hielt noch fünfzehn Jahre lang. Das Protokoll arbeitete ausschließlich nach dem Prinzip von Anfrage-Antwort und war hauptsächlich für die Übertragung von Textinformationen gedacht.
HTTP wurde entwickelt, um über dem TCP-Protokoll zu arbeiten, das die zuverlässige Zustellung von Paketen an den Empfänger garantiert. Die Funktionsweise von TCP beruht auf der Herstellung und Aufrechterhaltung einer zuverlässigen Verbindung zwischen Endpunkten und der Aufteilung des Datenverkehrs in Segmente. Segmente haben ihre eigene sequenzielle Nummer und Prüfziffer. Wenn eines der Segmente nicht ankommt oder mit einer falschen Prüfziffer ankommt, wird die Übertragung gestoppt, bis das verlorene Segment wiederhergestellt ist.
In HTTP/1.0 wurde die TCP-Verbindung nach jeder Anfrage geschlossen. Dies war äußerst verschwenderisch, da die Herstellung einer TCP-Verbindung (3-Way-Handshake) kein schneller Prozess ist. In HTTP/1.1 wurde ein Keep-Alive-Mechanismus eingeführt, der es ermöglicht, eine Verbindung für mehrere Anfragen wiederzuverwenden. Da es jedoch leicht zum Engpass werden kann, erlauben verschiedene Implementierungen von HTTP/1.1 die Eröffnung mehrerer TCP-Verbindungen zu einem Host. Beispielsweise sind in Chrome und in den neuesten Versionen von Firefox bis zu sechs Verbindungen zulässig.

Die Verschlüsselung sollte ebenfalls anderen Protokollen überlassen werden, und dafür wurde über TCP das TLS-Protokoll verwendet, das die Daten recht zuverlässig schützte, jedoch auch die Zeit, die zur Herstellung einer Verbindung benötigt wurde, weiter erhöhte. Letztendlich sah der Handshake-Prozess folgendermaßen aus:

Cloudflare-Illustration
So hatte HTTP/1.1 eine Reihe von Problemen:
- Langsame Verbindungsherstellung.
- Die Daten werden im Textformat übermittelt, was bedeutet, dass die Übertragung von Bildern, Videos und anderen nicht-textlichen Informationen ineffektiv ist.
- Eine TCP-Verbindung wird für eine Anfrage verwendet, was bedeutet, dass andere Anfragen entweder eine andere Verbindung finden oder warten müssen, bis die aktuelle Anfrage sie freigibt.
- Es wird nur das Pull-Modell unterstützt. Im Standard gibt es nichts über Server-Push.
- Die Header werden in Textform übermittelt.
Wenn Server-Push mehr oder weniger über das WebSocket-Protokoll implementiert wird, müssen die anderen Probleme radikaler angegangen werden.
Ein wenig Modernität: HTTP/2
Im Jahr 2012 begann Google mit der Entwicklung des SPDY-Protokolls (ausgesprochen „spidi“). Das Protokoll sollte die Hauptprobleme von HTTP/1.1 lösen und dabei abwärtskompatibel bleiben. Im Jahr 2015 stellte die IETF-Arbeitsgruppe die HTTP/2-Spezifikation vor, die auf dem SPDY-Protokoll basiert. Das sind die Unterschiede zu HTTP/2:
- Binäre Serialisierung.
- Multiplexing mehrerer HTTP-Anfragen über eine TCP-Verbindung.
- Server-Push out of the box (ohne WebSocket).
Das Protokoll war ein großer Fortschritt. Es bietet erheblich und erfordert keine Erstellung mehrerer TCP-Verbindungen: Alle Anfragen an einen Host werden in einer Multiplexverbindung abgewickelt. Das bedeutet, dass in einer Verbindung mehrere sogenannte Streams vorhanden sind, von denen jeder eine eigene ID hat. Dazu kommt der Server-Push als Bonus.
Allerdings führt das Multiplexing zu einem anderen grundlegenden Problem. Stellen Sie sich vor, wir führen asynchron 5 Anfragen an einen Server durch. Bei der Verwendung von HTTP/2 werden all diese Anfragen innerhalb einer einzigen TCP-Verbindung verarbeitet, was bedeutet, dass, wenn ein Segment einer beliebigen Anfrage verloren geht oder falsch ankommt, die Übertragung aller Anfragen und Antworten gestoppt wird, bis das verlorene Segment wiederhergestellt ist. Offensichtlich gilt: Je schlechter die Qualität der Verbindung, desto langsamer arbeitet HTTP/2. , zeigt HTTP/1.1 in Situationen, in denen verlorene Pakete 2 % aller Pakete ausmachen, eine bessere Leistung im Browser als HTTP/2, da es 6 Verbindungen öffnet, anstatt nur eine.
Dieses Problem wird als „head-of-line blocking“ bezeichnet und ist leider nicht zu lösen, wenn man TCP verwendet.

Illustration Daniel Steinberg
Als Ergebnis haben die Entwickler des HTTP/2-Standards eine enorme Menge Arbeit geleistet und nahezu alles getan, was auf Anwendungsebene des OSI-Modells möglich war. Es ist an der Zeit, in die Transportschicht hinabzusteigen und ein neues Transportprotokoll zu erfinden.
Wir benötigen ein neues Protokoll: UDP vs TCP
Es wurde ziemlich schnell klar, dass die Einführung eines völlig neuen Transportprotokolls in der heutigen Realität eine unlösbare Aufgabe ist. Der Grund dafür ist, dass die Hardware oder Mittelboxen (Router, Firewalls, NAT-Server...) über den Transportschichtniveau informiert sind, und es ist äußerst schwierig, sie etwas Neues lernen zu lassen. Darüber hinaus ist die Unterstützung für Transportprotokolle in den Betriebssystemkernen verankert, und die Kerne ändern sich auch nicht gerade freiwillig.
Hier könnte man die Hände sinken lassen und sagen: „Natürlich erfinden wir ein neues HTTP/3 mit Vorliebe für das Spiel und Kurtisanen, aber seine Einführung wird 10-15 Jahre dauern (ungefähr so lange wird es dauern, bis die meisten Geräte ersetzt werden)“, aber es gibt noch eine nicht so offensichtliche Alternative: die Verwendung des UDP-Protokolls. Ja, genau das Protokoll, mit dem wir in den späten 90ern und frühen 2000ern in lokalen Netzwerken Dateien hin und her schickten. Fast alle heutigen Geräte können damit arbeiten.
Was sind die Vorteile von UDP im Vergleich zu TCP? In erster Linie, dass wir keine Sitzung auf der Transportschicht haben, die die Hardware kennt. Das ermöglicht es uns, die Sitzung an den Endpunkten selbst zu definieren und dort auftretende Konflikte zu lösen. Das bedeutet, dass wir nicht auf ein oder mehrere Sitzungen (wie bei TCP) beschränkt sind, sondern so viele erstellen können, wie wir benötigen. Zweitens erfolgt die Datenübertragung über UDP schneller als über TCP. Theoretisch können wir so das heutige Geschwindigkeitslimit, das in HTTP/2 erreicht wurde, durchbrechen.
Allerdings garantiert UDP keine Zuverlässigkeit bei der Datenübertragung. Tatsächlich senden wir einfach Pakete und hoffen, dass sie am anderen Ende empfangen werden. Wurden sie nicht empfangen? Na ja, Pech gehabt… Das war ausreichend, um Videos für Erwachsene zu übertragen, aber für ernsthaftere Dinge benötigen wir Zuverlässigkeit, also müssen wir noch etwas über UDP legen.
Wie im Fall von HTTP/2 begann die Arbeit an der Schaffung eines neuen Protokolls bei Google im Jahr 2012, also ungefähr zur gleichen Zeit wie die Arbeit an SPDY. Im Jahr 2013 stellte Jim Roskind der breiten Öffentlichkeit vor. , und bereits 2015 wurde ein Internet Draft zur Standardisierung bei der IETF eingereicht. Zu diesem Zeitpunkt unterschied sich das von Roskind bei Google entwickelte Protokoll erheblich von dem zur Standardisierung vorgelegten, weshalb die Google-Version als gQUIC bezeichnet wurde.
Was ist QUIC?
Erstens, wie bereits erwähnt, ist es eine Wrapper über UDP. Auf UDP wird eine QUIC-Verbindung aufgebaut, in der es analog zu HTTP/2 mehrere Streams geben kann. Diese Streams existieren nur an den Endpunkten und werden unabhängig bedient. Wenn ein Paketverlust in einem Stream auftritt, hat dies keine Auswirkungen auf die anderen.

Illustration Daniel Steinberg
Zweitens wird die Verschlüsselung nicht mehr als separate Ebene implementiert, sondern ist im Protokoll integriert. Dies ermöglicht, Verbindungen herzustellen und öffentliche Schlüssel mit nur einem Handshake auszutauschen, und es erlaubt zudem die Verwendung des cleveren 0-RTT-Handshake-Mechanismus, um Verzögerungen beim Handshake vollständig zu vermeiden. Darüber hinaus können jetzt einzelne Datenpakete verschlüsselt werden. Dies ermöglicht es, die Annahme von Daten aus dem Stream nicht abzuwarten, sondern die empfangenen Pakete unabhängig zu entschlüsseln. Ein solcher Betriebsmodus war bei TCP überhaupt nicht möglich, da TLS und TCP unabhängig voneinander arbeiteten und TLS nicht wissen konnte, in welche Stücke die TCP-Daten zerlegt werden würden. Folglich konnte es seine Segmente nicht so vorbereiten, dass sie eins zu eins in die TCP-Segmente passten und unabhängig entschlüsselt werden konnten. All diese Verbesserungen ermöglichen es QUIC, die Latenz im Vergleich zu TCP zu reduzieren.

Drittens erlaubt das Konzept der leichten Streams, die Verbindung von der IP-Adresse des Clients zu entkoppeln. Dies ist wichtig, beispielsweise wenn der Client von einem Wi-Fi-Zugangspunkt zu einem anderen wechselt und dabei seine IP ändert. In diesem Fall kommt es bei der Nutzung von TCP zu einem langwierigen Prozess, bei dem bestehende TCP-Verbindungen aufgrund von Timeouts getrennt und neue Verbindungen mit der neuen IP aufgebaut werden. Bei QUIC hingegen sendet der Client einfach weiterhin Pakete mit der neuen IP, während er die alte Stream-ID verwendet. Da die Stream-ID jetzt einzigartig und nicht wiederverwendet wird, versteht der Server, dass der Client die IP gewechselt hat, sendet die verlorenen Pakete nach und setzt die Kommunikation an der neuen Adresse fort.
Viertens wird QUIC auf Anwendungsebene und nicht auf Betriebssystemebene implementiert. Dies ermöglicht einerseits, schneller Änderungen am Protokoll vorzunehmen, da es genügt, die Bibliothek zu aktualisieren, anstatt auf eine neue Version des Betriebssystems zu warten. Andererseits führt dies zu einem signifikanten Anstieg des CPU-Verbrauchs.
Und schließlich die Header. Die Kompression der Header gehört zu den Punkten, die sich in QUIC und gQUIC unterscheiden. Ich sehe keinen Sinn darin, viel Zeit darauf zu verwenden; ich sage nur, dass in der zur Standardisierung eingereichten Version die Kompression der Header maximal ähnlich zur Kompression der Header in HTTP/2 gestaltet wurde. Mehr dazu kann man lesen .
Wie viel schneller ist es?
Das ist eine komplizierte Frage. Tatsache ist, dass wir momentan keinen Standard haben, also gibt es nicht viel zu messen. Vielleicht sind die einzigen statistischen Daten, über die wir verfügen, die Daten von Google, das gQUIC seit 2013 nutzt und 2016 , dass etwa 90 % des Traffics, der von ihrem Chrome-Browser zu ihren Servern geht, jetzt QUIC verwendet. In derselben Präsentation berichten sie, dass Seiten über gQUIC etwa 5 % schneller geladen werden und es beim Streaming-Video etwa 30 % weniger Aussetzer im Vergleich zu TCP gibt.
Im Jahr 2017 veröffentlichte eine Gruppe von Forschern unter der Leitung von Arash Molavi Kakhki eine Untersuchung der Leistung von gQUIC im Vergleich zu TCP.
Die Studie deckte mehrere Schwächen von gQUIC auf, wie die Anfälligkeit für das Mischen von Netzwerkpaketen, Unfairness bei der Übertragungskapazität und eine langsamere Übertragung kleiner (bis 10 kB) Objekte. Letzteres kann jedoch durch die Nutzung von 0-RTT ausgeglichen werden. In allen anderen untersuchten Fällen zeigte gQUIC eine Geschwindigkeitssteigerung im Vergleich zu TCP. Über konkrete Zahlen ist hier schwer zu sprechen. Es ist besser, oder .
Hier sei gesagt, dass dies Daten über gQUIC sind und sie nicht für den in Entwicklung befindlichen Standard relevant sind. Was für QUIC sein wird, bleibt vorerst ein Geheimnis, aber es besteht die Hoffnung, dass die Schwächen, die bei gQUIC festgestellt wurden, berücksichtigt und behoben werden.
Ein Blick in die Zukunft: Was ist mit HTTP/3?
Hier ist alles kristallklar: Die API wird sich nicht ändern. Alles bleibt genau so, wie es in HTTP/2 war. Wenn die API unverändert bleibt, muss der Übergang zu HTTP/3 durch die Verwendung einer neuen Version der Bibliothek, die den Transport über QUIC unterstützt, auf der Backend-Seite erfolgen. Allerdings wird es noch lange dauern, bis wir auf ältere Versionen von HTTP zurückfallen müssen, da das Internet momentan nicht bereit ist für einen vollständigen Übergang zu UDP.
Wer unterstützt bereits
Hier bestehende QUIC-Implementierungen. Trotz des Fehlens eines Standards ist die Liste nicht schlecht.
Derzeit unterstützt kein Browser QUIC in einer Produktionsversion. Kürzlich gab es Informationen, dass Chrome die Unterstützung für HTTP/3 aktiviert hat, aber vorerst nur in der Canary-Version.
Von den Backends unterstützt nur und , allerdings vorerst experimentell. NGINX hat Ende Frühjahr 2019 , dass sie an der Unterstützung von HTTP/3 arbeiten, aber noch nicht fertig sind.
Welche Probleme gibt es
Wir leben in einer realen Welt, in der keine große Technologie ohne Widerstand in den Massen ankommen kann, und QUIC ist da keine Ausnahme.
Das Wichtigste ist, dass man dem Browser irgendwie erklären muss, dass "https://" jetzt nicht mehr garantiert auf den TCP-Port 443 führt. Es könnte dort sogar kein TCP vorhanden sein. Dafür wird der Alt-Svc-Header verwendet. Er ermöglicht es, dem Browser mitzuteilen, dass diese Website auch über ein bestimmtes Protokoll unter einer bestimmten Adresse verfügbar ist. In der Theorie sollte das einwandfrei funktionieren, aber in der Praxis werden wir feststellen, dass UDP beispielsweise auf der Firewall blockiert sein könnte, um DDoS-Angriffe zu verhindern.
Aber selbst wenn UDP nicht blockiert ist, kann der Client hinter einem NAT-Router stehen, der so konfiguriert ist, dass er die TCP-Session anhand der IP-Adresse aufrechterhält, und da wir UDP verwenden, das keine physikalische Sitzung hat, wird das NAT die Verbindung nicht aufrechterhalten und die QUIC-Session .
All diese Probleme hängen damit zusammen, dass UDP früher nicht für die Übertragung von Internetinhalten verwendet wurde und Hardwarehersteller nicht voraussehen konnten, dass das irgendwann passieren würde. Genauso verstehen Administratoren derzeit nicht wirklich, wie sie ihre Netzwerke richtig für QUIC konfigurieren sollten. Diese Situation wird sich allmählich ändern, und auf jeden Fall wird es weniger Zeit in Anspruch nehmen als die Einführung eines neuen Transportprotokolls.
Darüber hinaus erhöht QUIC, wie bereits beschrieben, die CPU-Auslastung erheblich. Daniel Stenberg den Anstieg der CPU-Nutzung auf das Dreifache.
Wann wird HTTP/3
Standard Bis Mai 2020, aber da aktuell immer noch Dokumente ausstehen, die für Juli 2019 geplant waren, kann man sagen, dass das Datum wahrscheinlich verschoben wird.
Google verwendet seine Implementation von gQUIC seit 2013. Wenn man sich eine HTTP-Anfrage ansieht, die an die Google-Suchmaschine gesendet wird, sieht man Folgendes:

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.
QUIC sieht derzeit wie eine relativ unausgereifte, aber sehr vielversprechende Technologie aus. Angesichts der Tatsache, dass die letzten 20 Jahre alle Optimierungen im Transportprotokoll hauptsächlich TCP betrafen, sieht QUIC, das in den meisten Fällen hinsichtlich der Leistung überlegen ist, bereits jetzt äußerst vielversprechend aus.
Es gibt jedoch noch ungelöste Probleme, die in den nächsten Jahren angegangen werden müssen. Der Prozess könnte sich verzögern, da die Hardware betroffen ist, die niemand gerne aktualisiert. Nichtsdestotrotz scheinen alle Probleme lösbar zu sein, und früher oder später werden wir alle HTTP/3 haben.
Die Zukunft steht vor der Tür!
Quelle: habr.com
