Unterstützung für HTTP/2-Server-Push ist auch in NGINX Plus R15 enthalten.
Wir freuen uns, Ihnen mitteilen zu können, dass NGINX 1.13.9 , veröffentlicht am 20. Februar 2018 , Unterstützung für HTTP/2-Server-Push bietet. Für NGINX Plus-Benutzer wird HTTP/2-Server-Push-Unterstützung in der kommenden NGINX Plus-Version R15 enthalten sein, die für April 2018 geplant ist.
Server Push, das in der HTTP/2-Spezifikation definiert ist, erlaubt es einem Server, Ressourcen proaktiv an einen Remote-Client zu senden, in dem Wissen, dass der Client diese Ressourcen bald anfordern könnte. So können Sie die Anzahl der RTTs (Round Trip Time – die Zeit für Anfrage und Antwort) bei einem Seitenladevorgang oft um eine RTT oder mehr verringern und den Nutzer damit schneller bedienen.
Mit Server-Push versorgen Sie einen Client vorab mit Stylesheets, Bildern und weiteren Ressourcen, die er zum Anzeigen einer Webseite benötigt. Achten Sie darauf, nur die tatsächlich notwendigen Ressourcen zu pushen und keine, die der Client wahrscheinlich bereits im Cache hat.
In diesem Blogbeitrag beschreibe ich:
nghttp
)Link-
HeadersUm beim Laden einer Seite Serverressourcen mitzuschieben, setzen Sie die Direktive http2_push
folgendermaßen ein:
server { # Stellen Sie sicher, dass HTTP/2 für den Server aktiviert ist. Listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # wenn ein Client demo.html anfordert, pushen Sie auch # /style.css, /image1.jpg und /image2.jpg location = /demo.html { http2_push /style.css; http2_push /image1.jpg; http2_push /image2.jpg; } }
Mit einer der beiden Methoden können Sie ganz einfach überprüfen, ob der Server-Push aktiv ist:
nghttp
So nutzen Sie die Entwicklertools Ihres Webbrowsers, um anhand von Google Chrome zu prüfen, ob Server Push aktiv ist. Im Beispiel zeigt die Spalte Initiator im Bereich Netzwerk der Entwicklertools von Chrome, dass mehrere Ressourcen als Teil der Anforderungsweiterleitung für /demo.html an den Client übertragen wurden.
nghttp
)Zusätzlich zu den Webbrowser-Tools können Sie den nghttp-
Befehlszeilenclient aus dem nghttp2.org -Projekt verwenden, um zu überprüfen, ob Server-Push aktiv ist. Sie können den nghttp
-Befehlszeilenclient von GitHub herunterladen oder das entsprechende Betriebssystempaket installieren, sofern verfügbar. Verwenden Sie für Ubuntu das Paket nghttp2-client
.
In der Ausgabe markiert das Sternchen (*) Ressourcen, die der Server aktiv bereitgestellt hat.
$ nghttp -ans https://example.com/demo.html ID AntwortEnde AnfrageStart Prozesscode Größe Anfragepfad 13 +84,25 ms +136us 84,11 ms 200 492 /demo.html 2 +84,33 ms * +84,09 ms 246us 200 266 /style.css 4 +261,94 ms * +84,12 ms 177,83 ms 200 40 K /image2.jpg 6 +685,95 ms * +84,12 ms 601,82 ms 200 173 K /image1.jpg
Oft ist es unbequem – oder sogar unmöglich –, die Ressourcen, die Sie pushen möchten, direkt in der NGINX-Konfigurationsdatei aufzulisten. Deshalb nutzt NGINX auch die Möglichkeit, Link-Preload-Header
abzufangen und die darin erkannten Ressourcen gezielt zu pushen. Aktivieren Sie das Preloading, indem Sie die Direktive http2_push_preload
in der Konfiguration hinzufügen:
server { # Stellen Sie sicher, dass HTTP/2 für den Server aktiviert ist. listen 443 ssl http2 ; ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem; root /var/www/html; # Link-Header abfangen und angeforderte Pushes initiieren location = /myapp { proxy_pass http://upstream; http2_push_preload on; } }
Wenn NGINX beispielsweise als Proxy fungiert (für HTTP, FastCGI oder andere Datenverkehrstypen), kann der Upstream-Server seiner Antwort einen Link
-Header wie diesen hinzufügen:
Verknüpfung: </style.css>; als=Stil; rel=preload
NGINX fängt diesen Header ab und leitet einen Server-Push von /style.css ein. Der Pfad im Link
-Header muss absolut sein – relative Pfade wie ./style.css werden nicht unterstützt. Der Pfad kann optional eine Abfragezeichenfolge enthalten.
Um mehrere Objekte zu pushen, können Sie mehrere Link
-Header angeben oder, noch besser, alle Objekte in eine durch Kommas getrennte Liste aufnehmen:
Verknüpfung: </style.css>; als=Stil; rel=preload, </favicon.ico>; als=Bild; rel=preload
Möchten Sie nicht, dass NGINX eine vorab geladene Ressource pusht, fügen Sie dem Header den Parameter nopush
hinzu:
# Ressource wird nicht gepushtLink: </nginx.png>; as=image; rel=preload; nopush
Wenn http2_push_preload
aktiviert ist, können Sie das Preload-Server-Push auch initiieren, indem Sie den Antwortheader in Ihrer NGINX-Konfiguration festlegen:
add_header Link "</style.css>; als=Stil; rel=preload";
Die HTTP/2-Spezifikation löst nicht das Problem, wann Ressourcen gepusht werden sollen. Es ist am effektivsten, Ressourcen nur dann an Ihre Clients zu senden, wenn Sie sicher sind, dass sie diese wirklich brauchen und diese wahrscheinlich nicht bereits im Cache vorliegen.
Ein Ansatz könnte darin bestehen, Ressourcen nur beim ersten Besuch der Website an den Client zu senden. Prüfen Sie zum Beispiel, ob ein Sitzungscookie vorhanden ist, und setzen Sie den Link
-Header nur dann, wenn kein Sitzungscookie gefunden wird. So laden Sie Ressourcen gezielt vor.
Wenn sich die Clients korrekt verhalten und das Cookie bei nachfolgenden Anfragen mitsenden, liefert NGINX die Ressourcen mit der folgenden Konfiguration pro Browsersitzung nur einmal an die Clients aus:
server {
listen 443 ssl http2 default_server;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
http2_push_preload on;
location = /demo.html {
add_header Set-Cookie "session=1";
add_header Link $resources;
}
}
map $http_cookie $resources {
"~*session=1" "";
default "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";
}
Um die Wirkung des Server-Pushs zu messen, haben wir eine einfache Testseite, /demo.html , erstellt, die auf ein separates Stylesheet, /style.css , verweist. Das Stylesheet verweist außerdem auf zwei Bilder. Wir haben die Seitenladezeiten mit drei verschiedenen Konfigurationen getestet:
GET
s (ohne Optimierung) – Der Browser lädt Ressourcen sofort, wenn er ihren Bedarf erkenntLink
-Header) wurden in die erste Antwort aufgenommen, um den Browser anzuweisen, die Abhängigkeiten zu ladenWir haben mehrere Testläufe jeder Konfiguration mit HTTP, HTTPS oder HTTP/2 durchgeführt. Die ersten beiden Konfigurationen gelten für alle drei Protokolle und Server-Push nur für HTTP/2.
Das Verhalten wurde mit den Chrome-Entwicklertools gemessen. Das am häufigsten vorkommende Verhalten jeder Konfiguration wurde bewertet und gemittelt, und die Zeiten wurden mit der RTT der Verbindung (gemessen mit Ping
) korreliert, um die mechanische Wirkung jeder Methode zu veranschaulichen.
GET
-Vorgang in etwa einer RTT abschließen.-GET
-Anfrage.keepalive_timeout
und http2_idle_timeout
wurden verwendet, um Keepalive-Verbindungen schnell zu schließen.Wir haben den Test bewusst einfach gestaltet, um die Funktionsweise von Preload-Hinweisen und Server Push klar zu zeigen. Server Push sorgt bei einfachen Szenarien für eine 1-RTT-Verbesserung gegenüber Preload-Hinweisen und bringt größere Vorteile im Vergleich zu nicht optimierten, sequenziellen GET
-Anfragen und der Erkennung abhängiger Ressourcen.
Realistischere Anwendungsfälle bringen deutlich mehr Variablen mit sich: mehrere abhängige Ressourcen, verschiedene Quellen und sogar das Risiko, Bandbreite mit bereits zwischengespeicherten oder momentan nicht benötigten Ressourcen zu verschwenden. Auch Unterschiede zwischen Browsern beeinflussen die Leistung. Ihre Ergebnisse werden bei diesem einfachen Test wahrscheinlich abweichen.
Das Chrome-Team hat beispielsweise einige ausführliche Empfehlungen dazu veröffentlicht, wann Server-Push bereitgestellt werden sollte, und hat auf komplexeren Sites Messungen durchgeführt, um die Auswirkungen von fehlender Optimierung, Vorladehinweisen und Server-Push über HTTP/2 zu vergleichen. Ihr Bericht „Faustregeln für HTTP/2-Push“ ist für jeden lesenswert, der den Einsatz von HTTP/2-Server-Push in der Produktion erwägt.
Die pragmatische Konsequenz: Wenn Sie die benötigten Ressourcen im Voraus kennen, lohnt es sich, Upstream-Server einen Preload-Hinweis senden zu lassen. Der Nutzen dieses Pushs ist zwar gering, aber messbar; er kann jedoch Bandbreite verschwenden und die Bereitstellung wichtiger Ressourcen verzögern. Testen und überwachen Sie Server-Push-Konfigurationen deshalb sorgfältig.
Die folgenden Informationen basieren teilweise auf den Untersuchungen in Jake Archibalds sehr detailliertem Blogbeitrag „HTTP/2-Push ist schwieriger als ich dachte“ .
HTTP/2-Server-Push senden wir normalerweise abhängige Ressourcen vorab, wenn Sie eine Ressource anfragen. Fordern Sie beispielsweise eine Webseite an, schickt der Server die zugehörigen Stylesheets, Schriftarten und Bilder aktiv mit.
Wenn Sie eine HTTP/2-Verbindung herstellen, kann der Server eine oder mehrere Server-Push-Antworten initiieren. Dabei sendet der Server Ressourcen, die Sie nicht explizit angefordert haben.
Der Client kann einen Push entweder ablehnen (durch Senden eines RST_STREAM-
Frames) oder akzeptieren. Der Client speichert den gepushten Inhalt in einem lokalen „Push-Cache“, der mit der HTTP/2-Verbindung verknüpft ist.
Wenn Sie später über eine bestehende HTTP/2-Verbindung eine Ressource anfordern, prüft das System den Push-Cache der Verbindung auf eine bereits abgeschlossene oder gerade übertragene Antwort. Es nutzt die zwischengespeicherte Ressource, bevor es eine neue HTTP/2-Anfrage stellt.
Eine gepushte Ressource bleibt im Push-Cache für die jeweilige Verbindung, bis (a) Sie sie verwenden oder (b) die HTTP/2-Verbindung geschlossen wird:
Dies hat mehrere Auswirkungen:
Eine viel detailliertere Liste der Probleme finden Sie in Jake Archibalds Blogbeitrag „HTTP/2-Push ist schwieriger als ich dachte“ .
HTTP/2-Server-Push ist eine interessante Funktion. Stellen Sie sicher, dass Sie die Push-Konfiguration Ihres HTTP/2-Servers gründlich testen und bereit sind, in Fällen auf Preload-Hinweise zurückzugreifen, in denen dies zu einem vorhersehbareren, Cache-bewussteren Verhalten führt.
„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."