HTTP / 1.1 vs HTTP / 2: Was ist der Unterschied?

Der Autor hat die Society of Women Engineers ausgewählt, um eine Spende als Teil der Write zu erhalten für DOnations program.

Einführung

Das Hypertext Transfer Protocol (HTTP) ist ein Anwendungsprotokoll, das seit seiner Erfindung im Jahr 1989 de facto der Standard für die Kommunikation im World Wide Web ist. Seit der Veröffentlichung von HTTP / 1.1 im Jahr 1997 bis vor kurzem wurden nur wenige Änderungen am Protokoll vorgenommen. Im Jahr 2015 kam jedoch eine überarbeitete Version namens HTTP / 2 zum Einsatz, die verschiedene Methoden zur Verringerung der Latenz bot, insbesondere bei mobilen Plattformen und serverintensiven Grafiken und Videos. Seitdem ist HTTP / 2 immer beliebter geworden. Schätzungen zufolge wird es von rund einem Drittel aller Websites auf der Welt unterstützt. In dieser sich wandelnden Landschaft können Webentwickler von den technischen Unterschieden zwischen HTTP / 1.1 und HTTP / 2 profitieren, um fundierte und effiziente Entscheidungen über die Entwicklung von Best Practices zu treffen.

Nachdem Sie diesen Artikel gelesen haben, werden Sie die Hauptunterschiede zwischen HTTP / 1.1 und HTTP / 2 verstehen und sich auf die technischen Änderungen konzentrieren, die HTTP / 2 vorgenommen hat, um ein effizienteres Webprotokoll zu erzielen.

Hintergrund

Um die spezifischen Änderungen, die HTTP / 2 an HTTP / 1.1 vorgenommen hat, in einen Kontext zu setzen, werfen wir zunächst einen Blick auf die historische Entwicklung und die grundlegenden Funktionsweisen der einzelnen Funktionen.

HTTP / 1.1

HTTP wurde 1989 von Timothy Berners-Lee als Kommunikationsstandard für das World Wide Web entwickelt und ist ein Anwendungsprotokoll der obersten Ebene, das Informationen zwischen einem Client-Computer und einem lokalen oder Remote-Webserver austauscht. In diesem Prozess sendet ein Client eine textbasierte Anforderung an einen Server, indem er eine Methode wie "+ GET " oder " POST +" aufruft. Als Antwort sendet der Server eine Ressource wie eine HTML-Seite zurück an den Client.

Angenommen, Sie besuchen eine Website unter der Domain "+ www.example.com +". Wenn Sie zu dieser URL navigieren, sendet der Webbrowser auf Ihrem Computer eine HTTP-Anfrage in Form einer textbasierten Nachricht, ähnlich der hier gezeigten:

GET /index.html HTTP/1.1
Host: www.example.com

Diese Anforderung verwendet die Methode "+ GET ", mit der Daten vom Hostserver abgefragt werden, der nach " Host: " aufgeführt ist. Als Antwort auf diese Anfrage sendet der Webserver " example.com +" eine HTML-Seite an den anfordernden Client zurück, zusätzlich zu allen Bildern, Stylesheets oder anderen Ressourcen, die im HTML benötigt werden. Beachten Sie, dass beim ersten Datenaufruf nicht alle Ressourcen an den Client zurückgegeben werden. Die Anforderungen und Antworten werden zwischen dem Server und dem Client hin und her verschoben, bis der Webbrowser alle Ressourcen erhalten hat, die zum Rendern des Inhalts der HTML-Seite auf Ihrem Bildschirm erforderlich sind.

Sie können sich diesen Austausch von Anforderungen und Antworten als eine einzelne Anwendungsschicht des Internetprotokollstapels vorstellen, die über der Übertragungsschicht (normalerweise mit dem Transmission Control Protocol oder TCP) und den Netzwerkschichten (mit dem Internetprotokoll oder IP) liegt ):

Es gibt viel zu besprechen über die unteren Ebenen dieses Stapels, aber um ein umfassendes Verständnis von HTTP / 2 zu erlangen, müssen Sie nur dieses abstrahierte Ebenenmodell kennen und wissen, wo sich HTTP darin befindet.

Mit dieser grundlegenden Übersicht über HTTP / 1.1 können wir nun die frühe Entwicklung von HTTP / 2 nacherzählen.

HTTP / 2

HTTP / 2 begann als SPDY-Protokoll und wurde in erster Linie bei Google entwickelt, um die Latenz beim Laden von Webseiten durch Techniken wie Komprimierung, Multiplexing und Priorisierung zu verringern. Dieses Protokoll diente als Vorlage für HTTP / 2, als die Hypertext Transfer Protocol-Arbeitsgruppe httpbis der IETF (Internet Engineering Task Force) den Standard zusammenstellte und in der Veröffentlichung von HTTP gipfelte / 2 im Mai 2015. Von Anfang an unterstützten viele Browser diese Standardisierungsanstrengungen, einschließlich Chrome, Opera, Internet Explorer und Safari. Zum Teil aufgrund dieser Browserunterstützung wurde das Protokoll seit 2015 in erheblichem Umfang übernommen, wobei besonders hohe Raten bei neuen Websites zu verzeichnen waren.

Aus technischer Sicht ist eines der wichtigsten Merkmale, das HTTP / 1.1 und HTTP / 2 unterscheidet, die Binärrahmenschicht, die als Teil der Anwendungsschicht im Internetprotokollstapel betrachtet werden kann. Im Gegensatz zu HTTP / 1.1, das alle Anforderungen und Antworten im Nur-Text-Format verwaltet, verwendet HTTP / 2 die Binärrahmenebene, um alle Nachrichten im Binärformat zu kapseln, während die HTTP-Semantik wie Verben, Methoden und Header beibehalten wird. Eine API auf Anwendungsebene würde weiterhin Nachrichten in den herkömmlichen HTTP-Formaten erstellen, die zugrunde liegende Ebene würde diese Nachrichten dann jedoch in Binärdateien konvertieren. Auf diese Weise wird sichergestellt, dass Webanwendungen, die vor HTTP / 2 erstellt wurden, bei der Interaktion mit dem neuen Protokoll weiterhin wie gewohnt funktionieren.

Durch die Umwandlung von Nachrichten in Binärdateien kann HTTP / 2 neue Ansätze für die Datenübermittlung ausprobieren, die in HTTP / 1.1 nicht verfügbar sind. Dies ist ein Gegensatz, der den praktischen Unterschieden zwischen den beiden Protokollen zugrunde liegt. Im nächsten Abschnitt wird auf das Bereitstellungsmodell von HTTP / 1.1 eingegangen, gefolgt von den neuen Modellen, die HTTP / 2 ermöglicht.

Liefermodelle

Wie bereits im vorherigen Abschnitt erwähnt, teilen sich HTTP / 1.1 und HTTP / 2 die Semantik und stellen so sicher, dass die Anforderungen und Antworten, die in beiden Protokollen zwischen Server und Client übertragen werden, ihre Ziele als traditionell formatierte Nachrichten mit Headern und Körpern erreichen GET + und + POST + `. Während HTTP / 1.1 diese in Klartextnachrichten überträgt, codiert HTTP / 2 diese in Binärdateien, wodurch sich die Möglichkeiten für Zustellmodelle erheblich unterscheiden. In diesem Abschnitt werden wir zunächst kurz untersuchen, wie HTTP / 1.1 versucht, die Effizienz mit seinem Bereitstellungsmodell und den daraus resultierenden Problemen zu optimieren, gefolgt von den Vorteilen der Binärrahmenschicht von HTTP / 2 und einer Beschreibung der Priorisierung Anfragen.

HTTP / 1.1 - Pipelining und Head-of-Line-Blocking

Die erste Antwort, die ein Client auf eine HTTP-Anforderung "+ GET +" erhält, ist häufig nicht die vollständig gerenderte Seite. Stattdessen enthält es Links zu zusätzlichen Ressourcen, die von der angeforderten Seite benötigt werden. Der Client stellt fest, dass für das vollständige Rendern der Seite diese zusätzlichen Ressourcen erst vom Server benötigt werden, nachdem die Seite heruntergeladen wurde. Aus diesem Grund muss der Client zusätzliche Anforderungen stellen, um diese Ressourcen abzurufen. In HTTP / 1.0 musste der Client die TCP-Verbindung bei jeder neuen Anforderung unterbrechen und neu erstellen, was sowohl zeit- als auch ressourcenaufwendig war.

HTTP / 1.1 behebt dieses Problem, indem persistente Verbindungen und Pipelining eingeführt werden. Bei dauerhaften Verbindungen geht HTTP / 1.1 davon aus, dass eine TCP-Verbindung geöffnet bleiben sollte, sofern nicht direkt angewiesen wird, die Verbindung zu schließen. Auf diese Weise kann der Client mehrere Anforderungen über dieselbe Verbindung senden, ohne auf eine Antwort zu warten, wodurch die Leistung von HTTP / 1.1 gegenüber HTTP / 1.0 erheblich verbessert wird.

Leider gibt es einen natürlichen Engpass bei dieser Optimierungsstrategie. Da sich mehrere Datenpakete nicht gegenseitig passieren können, wenn sie zum selben Ziel reisen, gibt es Situationen, in denen eine Anforderung am Kopf der Warteschlange, die die erforderliche Ressource nicht abrufen kann, alle dahinter stehenden Anforderungen blockiert. Dies ist als Head-of-Line-Blocking (HOL) bekannt und stellt ein erhebliches Problem bei der Optimierung der Verbindungseffizienz in HTTP / 1.1 dar. Durch das Hinzufügen separater, paralleler TCP-Verbindungen kann dieses Problem behoben werden. Die Anzahl gleichzeitiger TCP-Verbindungen zwischen einem Client und einem Server ist jedoch begrenzt. Für jede neue Verbindung sind erhebliche Ressourcen erforderlich.

Diese Probleme standen bei den HTTP / 2-Entwicklern im Vordergrund, die vorschlugen, die oben genannte Ebene für binäre Frames zu verwenden, um diese Probleme zu beheben. Im nächsten Abschnitt erfahren Sie mehr darüber.

HTTP / 2 - Vorteile der Binary Framing Layer

In HTTP / 2 codiert die Binärrahmenschicht Anforderungen / Antworten und zerlegt sie in kleinere Informationspakete, wodurch die Flexibilität der Datenübertragung erheblich erhöht wird.

Sehen wir uns genauer an, wie dies funktioniert. Im Gegensatz zu HTTP / 1.1, das mehrere TCP-Verbindungen verwenden muss, um den Effekt der HOL-Blockierung zu verringern, stellt HTTP / 2 ein einziges Verbindungsobjekt zwischen den beiden Computern her. Innerhalb dieser Verbindung gibt es mehrere Datenströme. Jeder Stream besteht aus mehreren Nachrichten im bekannten Anforderungs- / Antwortformat. Schließlich wird jede dieser Nachrichten in kleinere Einheiten namens frames aufgeteilt:

Auf der granularsten Ebene besteht der Kommunikationskanal aus einer Reihe binär codierter Frames, die jeweils einem bestimmten Stream zugeordnet sind. Die Identifizierungskennzeichen ermöglichen der Verbindung, diese Rahmen während der Übertragung zu verschachteln und sie am anderen Ende wieder zusammenzusetzen. Die verschachtelten Anforderungen und Antworten können parallel ausgeführt werden, ohne die dahinter liegenden Nachrichten zu blockieren. Dies wird als Multiplexing bezeichnet. Durch Multiplexing wird das Problem der Head-of-Line-Blockierung in HTTP / 1.1 behoben, indem sichergestellt wird, dass keine Nachricht warten muss, bis eine andere beendet ist. Dies bedeutet auch, dass Server und Clients gleichzeitig Anforderungen und Antworten senden können, was eine bessere Kontrolle und ein effizienteres Verbindungsmanagement ermöglicht.

Da der Client durch Multiplexing mehrere Streams gleichzeitig erstellen kann, muss für diese Streams nur eine einzige TCP-Verbindung verwendet werden. Eine einzige dauerhafte Verbindung pro Ursprung verbessert HTTP / 1.1, indem der Arbeitsspeicher und der Verarbeitungsaufwand im gesamten Netzwerk reduziert werden. Dies führt zu einer besseren Netzwerk- und Bandbreitennutzung und senkt somit die Gesamtbetriebskosten.

Eine einzelne TCP-Verbindung verbessert auch die Leistung des HTTPS-Protokolls, da der Client und der Server dieselbe gesicherte Sitzung für mehrere Anforderungen / Antworten wiederverwenden können. In HTTPS vereinbaren beide Parteien während des TLS- oder SSL-Handshakes die Verwendung eines einzelnen Schlüssels während der gesamten Sitzung. Wenn die Verbindung unterbrochen wird, wird eine neue Sitzung gestartet, die einen neu generierten Schlüssel für die weitere Kommunikation benötigt. Das Beibehalten einer einzelnen Verbindung kann daher die für die HTTPS-Leistung erforderlichen Ressourcen erheblich reduzieren. Beachten Sie, dass viele gängige Browser HTTP / 2 mit HTTPS nur unterstützen, obwohl die Verwendung der TLS-Schicht aufgrund von HTTP / 2-Spezifikationen nicht vorgeschrieben ist.

Obwohl das Multiplexing, das der Binär-Framing-Schicht inhärent ist, bestimmte Probleme von HTTP / 1.1 löst, können mehrere Streams, die auf dieselbe Ressource warten, immer noch Leistungsprobleme verursachen. Beim Entwurf von HTTP / 2 wird dies jedoch durch die Verwendung der Stream-Priorisierung berücksichtigt. Dieses Thema wird im nächsten Abschnitt behandelt.

HTTP / 2 - Stream-Priorisierung

Die Stream-Priorisierung behebt nicht nur das mögliche Problem von Anforderungen, die um dieselbe Ressource konkurrieren, sondern ermöglicht Entwicklern auch, das relative Gewicht von Anforderungen anzupassen, um die Anwendungsleistung besser zu optimieren. In diesem Abschnitt werden wir den Prozess dieser Priorisierung aufschlüsseln, um einen besseren Einblick zu erhalten, wie Sie diese Funktion von HTTP / 2 nutzen können.

Wie Sie jetzt wissen, organisiert die Binärrahmenebene Nachrichten in parallelen Datenströmen. Wenn ein Client gleichzeitig Anforderungen an einen Server sendet, kann er die angeforderten Antworten priorisieren, indem er jedem Stream eine Gewichtung zwischen 1 und 256 zuweist. Die höhere Zahl gibt eine höhere Priorität an. Darüber hinaus gibt der Client die Abhängigkeit jedes Streams von einem anderen Stream an, indem er die ID des Streams angibt, von dem er abhängt. Wenn der übergeordnete Bezeichner weggelassen wird, wird davon ausgegangen, dass der Stream vom Root-Stream abhängt. Dies ist in der folgenden Abbildung dargestellt:

In der Abbildung enthält der Kanal sechs Streams mit jeweils einer eindeutigen ID und einem bestimmten Gewicht. Stream 1 ist keine übergeordnete ID zugeordnet und ist standardmäßig dem Stammknoten zugeordnet. Bei allen anderen Streams ist eine übergeordnete ID markiert. Die Ressourcenzuweisung für jeden Stream basiert auf dem Gewicht, das sie enthalten, und den Abhängigkeiten, die sie benötigen. Beispielsweise haben die Streams 5 und 6, denen in der Abbildung dasselbe Gewicht und derselbe übergeordnete Stream zugewiesen wurden, die gleiche Priorisierung für die Ressourcenzuweisung.

Der Server erstellt anhand dieser Informationen einen Abhängigkeitsbaum, mit dem der Server die Reihenfolge bestimmen kann, in der die Anforderungen ihre Daten abrufen. Basierend auf den Streams in der vorhergehenden Abbildung sieht der Abhängigkeitsbaum wie folgt aus:

image: http: //assets.digitalocean.com/articles/cart_63893/Dependency_Tree.png [Abhängigkeitsbaum]

In diesem Abhängigkeitsbaum ist Stream 1 vom Root-Stream abhängig, und es gibt keinen anderen Stream, der vom Root-Stream abgeleitet wurde, sodass alle verfügbaren Ressourcen vor den anderen Streams Stream 1 zugewiesen werden. Da der Baum anzeigt, dass Stream 2 vom Abschluss von Stream 1 abhängt, wird Stream 2 erst fortgesetzt, wenn die Task von Stream 1 abgeschlossen ist. Betrachten wir nun die Streams 3 und 4. Diese beiden Streams hängen von Stream 2 ab. Wie im Fall von Stream 1 erhält Stream 2 alle verfügbaren Ressourcen vor Stream 3 und 4. Nachdem Stream 2 seine Aufgabe abgeschlossen hat, erhalten Stream 3 und 4 die Ressourcen. Diese werden entsprechend ihrer Gewichtung im Verhältnis 2: 4 aufgeteilt, was zu einem höheren Anteil der Ressourcen für Stream 4 führt. Wenn Stream 3 beendet ist, erhalten Stream 5 und 6 die verfügbaren Ressourcen zu gleichen Teilen. Dies kann geschehen, bevor Stream 4 seine Aufgabe beendet hat, obwohl Stream 4 einen höheren Ressourcenblock erhält. Streams auf einer niedrigeren Ebene können gestartet werden, sobald die abhängigen Streams auf einer höheren Ebene beendet sind.

Als Anwendungsentwickler können Sie die Gewichtung Ihrer Anforderungen entsprechend Ihren Anforderungen festlegen. Beispielsweise können Sie dem Laden eines Bildes mit hoher Auflösung eine niedrigere Priorität zuweisen, nachdem Sie ein Miniaturbild auf der Webseite bereitgestellt haben. Durch diese Möglichkeit der Gewichtszuweisung ermöglicht HTTP / 2 Entwicklern eine bessere Kontrolle über das Rendern von Webseiten. Das Protokoll ermöglicht es dem Client auch, Abhängigkeiten zu ändern und Gewichte zur Laufzeit als Reaktion auf Benutzerinteraktionen neu zuzuweisen. Es ist jedoch wichtig zu beachten, dass ein Server die zugewiesenen Prioritäten selbst ändern kann, wenn ein bestimmter Stream für den Zugriff auf eine bestimmte Ressource gesperrt ist.

Pufferüberlauf

Bei jeder TCP-Verbindung zwischen zwei Computern steht sowohl dem Client als auch dem Server eine bestimmte Menge an Pufferplatz zur Verfügung, um eingehende Anforderungen aufzunehmen, die noch nicht verarbeitet wurden. Diese Puffer bieten Flexibilität zur Berücksichtigung zahlreicher oder besonders großer Anforderungen sowie ungleichmäßiger Geschwindigkeiten von Downstream- und Upstream-Verbindungen.

Es gibt jedoch Situationen, in denen ein Puffer nicht ausreicht. Beispielsweise überträgt der Server möglicherweise eine große Datenmenge mit einer Geschwindigkeit, die die Clientanwendung aufgrund einer begrenzten Puffergröße oder einer geringeren Bandbreite nicht bewältigen kann. Wenn ein Client ein großes Bild oder ein Video auf einen Server hochlädt, kann der Serverpuffer überlaufen, wodurch zusätzliche Pakete verloren gehen.

Um einen Pufferüberlauf zu vermeiden, muss ein Flusssteuerungsmechanismus verhindern, dass der Absender den Empfänger mit Daten überflutet. In diesem Abschnitt erhalten Sie einen Überblick darüber, wie HTTP / 1.1 und HTTP / 2 unterschiedliche Versionen dieses Mechanismus verwenden, um mit der Flusssteuerung gemäß den verschiedenen Bereitstellungsmodellen umzugehen.

HTTP / 1.1

In HTTP / 1.1 basiert die Flusssteuerung auf der zugrunde liegenden TCP-Verbindung. Wenn diese Verbindung hergestellt wird, richten sowohl der Client als auch der Server ihre Puffergrößen mit ihren Systemstandardeinstellungen ein. Wenn der Puffer des Empfängers teilweise mit Daten gefüllt ist, teilt er dem Absender sein Empfangsfenster mit, d. H. Die Menge des verfügbaren Speicherplatzes, der in seinem Puffer verbleibt. Dieses Empfangsfenster wird in einem Signal angekündigt, das als ACK-Paket bekannt ist. Dies ist das Datenpaket, das der Empfänger sendet, um zu bestätigen, dass er das Öffnungssignal empfangen hat. Wenn dieses angekündigte Empfangsfenster die Größe Null hat, sendet der Absender keine Daten mehr, bis der Client seinen internen Puffer löscht und dann die Fortsetzung der Datenübertragung anfordert. Hierbei ist zu beachten, dass die Verwendung von Empfangsfenstern, die auf der zugrunde liegenden TCP-Verbindung basieren, die Flusssteuerung nur an beiden Enden der Verbindung implementieren kann.

Da HTTP / 1.1 auf der Transportschicht basiert, um einen Pufferüberlauf zu vermeiden, erfordert jede neue TCP-Verbindung einen separaten Flusssteuerungsmechanismus. HTTP / 2 multiplext jedoch Streams innerhalb einer einzelnen TCP-Verbindung und muss die Flusssteuerung auf andere Weise implementieren.

HTTP / 2

HTTP / 2 multiplext Datenströme innerhalb einer einzelnen TCP-Verbindung. Infolgedessen reichen Empfangsfenster auf der Ebene der TCP-Verbindung nicht aus, um die Zustellung einzelner Streams zu regeln. HTTP / 2 löst dieses Problem, indem Client und Server ihre eigenen Ablaufsteuerungen implementieren können, anstatt sich auf die Transportschicht zu verlassen. Die Anwendungsschicht teilt den verfügbaren Pufferplatz mit, sodass der Client und der Server das Empfangsfenster auf die Ebene der gemultiplexten Streams einstellen können. Diese feinskalige Flusssteuerung kann nach der ersten Verbindung über einen Rahmen "+ WINDOW_UPDATE +" geändert oder beibehalten werden.

Da dieses Verfahren den Datenfluss auf der Ebene der Anwendungsschicht steuert, muss der Flusssteuerungsmechanismus nicht warten, bis ein Signal sein endgültiges Ziel erreicht, bevor das Empfangsfenster angepasst wird. Zwischenknoten können die Informationen zu den Einstellungen für die Ablaufsteuerung verwenden, um ihre eigenen Ressourcenzuweisungen zu ermitteln und entsprechend zu ändern. Auf diese Weise kann jeder Vermittlungsserver seine eigene benutzerdefinierte Ressourcenstrategie implementieren, wodurch eine höhere Verbindungseffizienz erzielt wird.

Diese Flexibilität bei der Ablaufsteuerung kann bei der Erstellung geeigneter Ressourcenstrategien vorteilhaft sein. Beispielsweise kann der Client den ersten Scan eines Bildes abrufen, es dem Benutzer anzeigen und dem Benutzer ermöglichen, eine Vorschau des Bildes anzuzeigen, während er kritischere Ressourcen abruft. Sobald der Client diese kritischen Ressourcen abgerufen hat, nimmt der Browser den Abruf des verbleibenden Teils des Bildes wieder auf. Wenn Sie die Implementierung der Flusssteuerung auf Client und Server verschieben, kann dies die wahrgenommene Leistung von Webanwendungen verbessern.

In Bezug auf die Flusssteuerung und die in einem früheren Abschnitt erwähnte Stream-Priorisierung bietet HTTP / 2 eine detailliertere Steuerungsebene, die die Möglichkeit einer umfassenderen Optimierung eröffnet. Im nächsten Abschnitt wird eine andere für das Protokoll einzigartige Methode erläutert, mit der eine Verbindung auf ähnliche Weise verbessert werden kann: Vorhersagen von Ressourcenanforderungen mit server push.

Vorhersagen von Ressourcenanforderungen

In einer typischen Webanwendung sendet der Client eine "+ GET " - Anforderung und empfängt eine HTML-Seite, normalerweise die Indexseite der Site. Beim Untersuchen des Inhalts der Indexseite stellt der Client möglicherweise fest, dass er zusätzliche Ressourcen wie CSS- und JavaScript-Dateien abrufen muss, um die Seite vollständig zu rendern. Der Client stellt fest, dass er diese zusätzlichen Ressourcen erst benötigt, nachdem er die Antwort von seiner anfänglichen " GET +" - Anforderung erhalten hat, und muss daher zusätzliche Anforderungen stellen, um diese Ressourcen abzurufen und die Zusammenstellung der Seite abzuschließen. Diese zusätzlichen Anforderungen erhöhen letztendlich die Verbindungsladezeit.

Es gibt jedoch Lösungen für dieses Problem: Da der Server im Voraus weiß, dass der Client zusätzliche Dateien benötigt, kann der Server dem Client Zeit sparen, indem er diese Ressourcen an den Client sendet, bevor er sie anfordert. HTTP / 1.1 und HTTP / 2 verfolgen unterschiedliche Strategien, die jeweils im nächsten Abschnitt beschrieben werden.

HTTP / 1.1 - Inlining von Ressourcen

Wenn der Entwickler in HTTP / 1.1 im Voraus weiß, welche zusätzlichen Ressourcen der Clientcomputer benötigt, um die Seite zu rendern, kann er die erforderliche Ressource mithilfe der Methode resource inlining direkt in das HTML-Dokument aufnehmen, das der Server als Antwort auf das sendet anfängliche + GET + Anfrage. Wenn ein Client zum Rendern einer Seite beispielsweise eine bestimmte CSS-Datei benötigt, wird dem Client durch Inlining dieser CSS-Datei die erforderliche Ressource zur Verfügung gestellt, bevor er danach fragt, wodurch sich die Gesamtzahl der vom Client zu sendenden Anforderungen verringert.

Es gibt jedoch einige Probleme mit dem Inlining von Ressourcen. Das Einbeziehen der Ressource in das HTML-Dokument ist eine praktikable Lösung für kleinere, textbasierte Ressourcen. Größere Dateien in Nicht-Text-Formaten können jedoch die Größe des HTML-Dokuments erheblich erhöhen, was letztendlich die Verbindungsgeschwindigkeit verringern und den ursprünglichen Vorteil zunichte machen kann von dieser Technik verwenden. Da die eingebetteten Ressourcen nicht mehr vom HTML-Dokument getrennt sind, gibt es für den Client keinen Mechanismus, um bereits vorhandene Ressourcen abzulehnen oder eine Ressource in den Cache zu stellen. Wenn für mehrere Seiten die Ressource erforderlich ist, wird für jedes neue HTML-Dokument dieselbe Ressource in den Code eingefügt, was zu größeren HTML-Dokumenten und längeren Ladezeiten führt, als wenn die Ressource zu Beginn einfach zwischengespeichert worden wäre.

Ein Hauptnachteil des Inlinings von Ressourcen ist daher, dass der Client die Ressource und das Dokument nicht trennen kann. Um die Verbindung zu optimieren, ist eine genauere Steuerung erforderlich. HTTP / 2 versucht, die Server-Push-Anforderungen zu erfüllen.

HTTP / 2 - Server Push

Da HTTP / 2 mehrere gleichzeitige Antworten auf die anfängliche Anforderung "+ GET +" eines Clients ermöglicht, kann ein Server eine Ressource zusammen mit der angeforderten HTML-Seite an einen Client senden und die Ressource bereitstellen, bevor der Client danach fragt. Dieser Prozess heißt server push. Auf diese Weise kann eine HTTP / 2-Verbindung das gleiche Ziel der Ressourcen-Inlining erreichen, während die Trennung zwischen der übertragenen Ressource und dem Dokument beibehalten wird. Dies bedeutet, dass der Client entscheiden kann, die übertragene Ressource getrennt vom Haupt-HTML-Dokument zwischenzuspeichern oder abzulehnen, wodurch der Hauptnachteil der Ressourcen-Inlining behoben wird.

In HTTP / 2 beginnt dieser Prozess, wenn der Server einen "+ PUSH_PROMISE " - Frame sendet, um den Client darüber zu informieren, dass er eine Ressource pushen wird. Dieser Frame enthält nur den Header der Nachricht und ermöglicht es dem Client, im Voraus zu wissen, welche Ressource der Server pusht. Wenn die Ressource bereits zwischengespeichert ist, kann der Client den Push ablehnen, indem er als Antwort einen Rahmen " RST_STREAM " sendet. Der Rahmen " PUSH_PROMISE +" verhindert außerdem, dass der Client eine doppelte Anforderung an den Server sendet, da er weiß, welche Ressourcen der Server pushen wird.

Hierbei ist zu beachten, dass der Schwerpunkt des Server-Pushs auf der Client-Steuerung liegt. Wenn ein Client die Priorität des Server-Push anpassen oder sogar deaktivieren muss, kann er jederzeit einen Rahmen "+ SETTINGS +" senden, um diese HTTP / 2-Funktion zu ändern.

Obwohl diese Funktion ein großes Potenzial aufweist, ist Server-Push nicht immer die Antwort auf die Optimierung Ihrer Webanwendung. Beispielsweise können einige Webbrowser Push-Anforderungen nicht immer abbrechen, selbst wenn der Client die Ressource bereits zwischengespeichert hat. Wenn der Client versehentlich zulässt, dass der Server eine doppelte Ressource sendet, kann der Server-Push die Verbindung unnötig belegen. Am Ende sollte Server-Push nach Ermessen des Entwicklers verwendet werden. Weitere Informationen zur strategischen Verwendung von Server-Push und zur Optimierung von Webanwendungen finden Sie unter PRPL pattern, das von Google entwickelt wurde. Weitere Informationen zu den möglichen Problemen mit Server-Push finden Sie im Blog-Beitrag von Jake Archibald unter https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/[HTTP/2-Push ist härter als ich dachte.

Kompression

Eine übliche Methode zur Optimierung von Webanwendungen ist die Verwendung von Komprimierungsalgorithmen, um die Größe von HTTP-Nachrichten zu verringern, die zwischen dem Client und dem Server übertragen werden. HTTP / 1.1 und HTTP / 2 verwenden beide diese Strategie, aber bei ersteren treten Implementierungsprobleme auf, die das Komprimieren der gesamten Nachricht verhindern. Im folgenden Abschnitt wird erläutert, warum dies der Fall ist und wie HTTP / 2 eine Lösung bieten kann.

HTTP / 1.1

Programme wie gzip werden seit langem verwendet, um die in HTTP-Nachrichten gesendeten Daten zu komprimieren, insbesondere um die Größe von CSS- und JavaScript-Dateien zu verringern. Die Header-Komponente einer Nachricht wird jedoch immer als Klartext gesendet. Obwohl jeder Header recht klein ist, belastet die Last dieser unkomprimierten Daten die Verbindung immer mehr, je mehr Anforderungen gestellt werden. Dies wirkt sich insbesondere negativ auf komplizierte, API-lastige Webanwendungen aus, die viele verschiedene Ressourcen und somit viele verschiedene Ressourcenanforderungen erfordern. Darüber hinaus können durch die Verwendung von Cookies die Kopfzeilen manchmal sehr viel größer werden, wodurch eine gewisse Komprimierung erforderlich wird.

Um diesen Engpass zu beheben, verwendet HTTP / 2 die HPACK-Komprimierung, um die Größe der Header zu verringern. Dieses Thema wird im nächsten Abschnitt näher erläutert.

HTTP / 2

Eines der Themen, die in HTTP / 2 immer wieder auftauchen, ist die Möglichkeit, die Binärrahmenebene zu verwenden, um eine bessere Kontrolle über feinere Details zu erzielen. Gleiches gilt für die Header-Komprimierung. HTTP / 2 kann Header von ihren Daten trennen, was zu einem Header-Frame und einem Daten-Frame führt. Das HTTP / 2-spezifische Komprimierungsprogramm HPACK kann diesen Header-Frame dann komprimieren. Dieser Algorithmus kann die Header-Metadaten mithilfe der Huffman-Codierung codieren und dadurch die Größe erheblich verringern. Zusätzlich kann HPACK zuvor übermittelte Metadatenfelder nachverfolgen und sie gemäß einem dynamisch geänderten Index, der von Client und Server gemeinsam genutzt wird, weiter komprimieren. Nehmen Sie beispielsweise die folgenden zwei Anforderungen an:

Anfrage Nr. 1

method:     GET
scheme:     https
host:       example.com
path:       /academy
accept:     /image/jpeg
user-agent: Mozilla/5.0 ...

Anfrage Nr. 2

method:     GET
scheme:     https
host:       example.com
path:       /academy/images
accept:     /image/jpeg
user-agent: Mozilla/5.0 ...

Die verschiedenen Felder in diesen Anforderungen, wie z. B. "+ method i", "+ scheme &", "+ host ", " accept" und "+ user-agent", haben dieselben Werte. Nur das Feld "+ Pfad " verwendet einen anderen Wert. Folglich kann der Client beim Senden von " Request # 2 " HPACK verwenden, um nur die indizierten Werte zu senden, die zum Rekonstruieren dieser allgemeinen Felder und zum erneuten Codieren des " path +" - Felds erforderlich sind. Die resultierenden Header-Frames lauten wie folgt:

Header-Frame für Anforderung Nr. 1

method:     GET
scheme:     https
host:       example.com
path:       /academy
accept:     /image/jpeg
user-agent: Mozilla/5.0 ...

Header Frame für Request # 2

path:       /academy/images

Mit HPACK und anderen Komprimierungsmethoden bietet HTTP / 2 eine weitere Funktion, mit der die Client-Server-Latenz verringert werden kann.

Fazit

Wie Sie anhand dieser Punkt-für-Punkt-Analyse sehen können, unterscheidet sich HTTP / 2 in vielerlei Hinsicht von HTTP / 1.1. Einige Funktionen bieten ein höheres Maß an Kontrolle, mit dem die Leistung von Webanwendungen besser optimiert werden kann vorheriges Protokoll. Nachdem Sie sich einen umfassenden Überblick über die Unterschiede zwischen den beiden Protokollen verschafft haben, können Sie überlegen, wie sich Faktoren wie Multiplexing, Stream-Priorisierung, Flusskontrolle, Server-Push und Komprimierung in HTTP / 2 auf die sich ändernde Landschaft der Webentwicklung auswirken .

Wenn Sie einen Leistungsvergleich zwischen HTTP / 1.1 und HTTP / 2 wünschen, lesen Sie diese Google-Demo, in der die Protokolle für verschiedene Latenzen verglichen werden. Beachten Sie, dass beim Ausführen des Tests auf Ihrem Computer die Ladezeiten der Seiten abhängig von verschiedenen Faktoren wie Bandbreite, verfügbaren Client- und Serverressourcen zum Zeitpunkt des Tests usw. variieren können. Wenn Sie die Ergebnisse ausführlicherer Tests untersuchen möchten, lesen Sie den Artikel HTTP/2 - A Real- Weltleistungstest und Analyse. Wenn Sie außerdem erfahren möchten, wie Sie eine moderne Webanwendung erstellen, können Sie unserer https://www.digitalocean.com/community/tutorials/how-to-build-a-modern-web-application-to- folgen. Verwalten von Kundeninformationen mit Django und Reagieren auf Ubuntu 18-04 [Erstellen einer modernen Webanwendung zum Verwalten von Kundeninformationen mit Django und Reagieren auf Ubuntu 18.04 2 Server mit unserer How To Set Up Nginx with HTTP / 2-Unterstützung unter Ubuntu 16.04 Tutorial.