Unterstützung für HTTP/2 Server Push ist auch in NGINX Plus R15 enthalten.
Wir freuen uns, bekannt geben zu können, dass NGINX 1.13.9, das am 20. Februar 2018 veröffentlicht wurde, HTTP/2 Server Push unterstützt. Für Benutzer von NGINX Plus wird die Unterstützung für HTTP/2 Server Push in der kommenden Version NGINX Plus R15 enthalten sein, deren Veröffentlichung für April 2018 geplant ist.
Server-Push, der in der HTTP/2-Spezifikation definiert ist, ermöglicht es einem Server, Ressourcen proaktiv an einen entfernten Client zu übertragen, wenn davon auszugehen ist, dass der Client diese Ressourcen in Kürze anfordern wird. Dadurch lässt sich die Anzahl der RTTs (Round Trip Time – die für eine Anfrage und Antwort benötigte Zeit) beim Laden einer Seite potenziell um eine oder mehrere RTTs reduzieren, sodass der Benutzer schneller eine Antwort erhält.
Server-Push kann verwendet werden, um einem Client vorab Stylesheets, Bilder und andere Ressourcen bereitzustellen, die er zum Rendern einer Webseite benötigt. Achten Sie darauf, nur erforderliche Ressourcen zu übertragen. Übertragen Sie keine Ressourcen, die der Client wahrscheinlich bereits im Cache gespeichert hat.
In diesem Blogbeitrag beschreibe ich:
- Grundkonfiguration für HTTP/2 Server Push
- So überprüfen Sie, ob HTTP/2 Server Push funktioniert (mithilfe von Browser-Tools oder
nghttp) - Inhalte automatisch über den
Link-Header pushen - Inhalte selektiv per Push übertragen
- Messung der Auswirkungen von HTTP/2 Server Push
HTTP/2 Server Push konfigurieren
Um Ressourcen zusammen mit dem Laden einer Seite zu übertragen, verwenden Sie die Direktive „http2_push“ wie folgt:
server { # Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
# whenever a client requests demo.html, also push
# /style.css, /image1.jpg and /image2.jpg
location = /demo.html {
http2_push /style.css; http2_push /image1.jpg; http2_push /image2.jpg;
}
}HTTP/2-Server-Push überprüfen
Sie können ganz einfach mit einer von zwei Methoden überprüfen, ob Server Push aktiv ist:
- Die Entwicklertools in Ihrem Webbrowser
- Ein HTTP/2-Client für die Befehlszeile wie etwa
nghttp
Überprüfung mit den Entwicklertools (Google Chrome)
Im Folgenden wird am Beispiel von Google Chrome erläutert, wie Sie mit den Entwicklertools Ihres Webbrowsers überprüfen können, ob Server Push aktiv ist. In der Abbildung zeigt die Spalte „Initiator“ auf der Registerkarte „Network“ der Chrome-Entwicklertools, dass im Rahmen einer Anfrage für „/demo.html“ mehrere Ressourcen an den Client übertragen wurden.

Überprüfung mit einem Befehlszeilen-Client (nghttp)
Zusätzlich zu den Webbrowser-Tools können Sie den Befehlszeilen-Client nghttp aus dem Projekt nghttp2.org verwenden, um zu überprüfen, ob Server Push aktiviert ist. Sie können den Befehlszeilen-Client nghttp von GitHub herunterladen oder, sofern verfügbar, das entsprechende Betriebssystempaket installieren. Verwenden Sie für Ubuntu das Paket nghttp2-client.
In der Ausgabe kennzeichnet das Sternchen (*) Ressourcen, die vom Server per Push übertragen wurden.
$ nghttp -ans https://example.com/demo.htmlid responseEnd requestStart process code size request path
13 +84.25ms +136us 84.11ms 200 492 /demo.html
2 +84.33ms * +84.09ms 246us 200 266 /style.css
4 +261.94ms * +84.12ms 177.83ms 200 40K /image2.jpg
6 +685.95ms * +84.12ms 601.82ms 200 173K /image1.jpgRessourcen automatisch an Clients übertragen
In vielen Situationen ist es umständlich – oder sogar unmöglich –, die Ressourcen, die per Push übertragen werden sollen, in der NGINX-Konfigurationsdatei aufzulisten. Daher unterstützt NGINX auch das Abfangen von Link-Preload-Headern, um anschließend die in diesen Headern angegebenen Ressourcen per Push zu übertragen. Um Preload zu aktivieren, fügen Sie die Direktive http2_push_preload in die Konfiguration ein:
server { # Ensure that HTTP/2 is enabled for the server
listen 443 ssl http2;
ssl_certificate ssl/certificate.pem;
ssl_certificate_key ssl/key.pem;
root /var/www/html;
# Intercept Link header and initiate requested Pushes
location = /myapp {
proxy_pass http://upstream;
http2_push_preload on;
}
}Wenn NGINX beispielsweise als Proxy fungiert (für HTTP, FastCGI oder andere Arten von Datenverkehr), kann der Upstream-Server seiner Antwort einen Link-Header wie diesen hinzufügen:
Link: </style.css>; as=style; rel=preloadNGINX fängt diesen Header ab und startet einen Server-Push von /style.css. Der Pfad im Link-Header muss absolut sein – relative Pfade wie ./style.css werden nicht unterstützt. Der Pfad kann optional einen Abfragestring enthalten.
Um mehrere Objekte per Push zu übertragen, können Sie mehrere Link-Header angeben oder, noch besser, alle Objekte in einer durch Kommas getrennten Liste aufführen:
Link: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preloadWenn Sie nicht möchten, dass NGINX eine vorab geladene Ressource per Push überträgt, fügen Sie dem Header den Parameter „nopush“ hinzu:
# Resource is not pushedLink: </nginx.png>; as=image; rel=preload; nopushWenn http2_push_preload aktiviert ist, können Sie den Preload-Server-Push auch initiieren, indem Sie den Antwort-Header in Ihrer NGINX-Konfiguration festlegen:
add_header Link "</style.css>; as=style; rel=preload";Ressourcen selektiv an Clients pushen
Die HTTP/2-Spezifikation geht nicht auf die Herausforderung ein, zu entscheiden, ob Ressourcen per Push übertragen werden sollen. Es ist eindeutig am besten, Ressourcen nur dann per Push an Clients zu übertragen, wenn Sie sowohl wissen, dass diese die Ressource wahrscheinlich benötigen, als auch, dass sie diese wahrscheinlich noch nicht im Cache haben.
Ein möglicher Ansatz besteht darin, Ressourcen nur beim ersten Besuch der Website an die Clients zu übertragen. Sie können beispielsweise prüfen, ob ein Sitzungscookie vorhanden ist, und den Link-Header nur unter bestimmten Bedingungen setzen, sodass die Ressourcen nur dann vorab geladen werden, wenn kein Sitzungscookie vorhanden ist.
Unter der Annahme, dass sich die Clients ordnungsgemäß verhalten und das Cookie bei nachfolgenden Anfragen mitsenden, überträgt NGINX die Ressourcen mit der folgenden Konfiguration nur einmal pro Browsersitzung an die Clients:
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";
}Messung der Auswirkungen von HTTP/2 Server Push
Um die Auswirkungen von Server Push zu messen, haben wir eine einfache Testseite erstellt: /demo.html, die auf ein separates Stylesheet verweist: /style.css. Das Stylesheet verweist wiederum auf zwei Bilder. Wir haben die Seitenladezeiten mit drei verschiedenen Konfigurationen getestet:
- Sequenzielle
GETs (keine Optimierung) – Der Browser lud Ressourcen, sobald er feststellte, dass sie benötigt wurden - Preload-Hinweise – Preload-Hinweise (
Link-Header) waren in der ersten Antwort enthalten, um den Browser anzuweisen, die Abhängigkeiten zu laden - Server-Push (nur HTTP/2) – Abhängigkeiten wurden präventiv an den Browser übertragen

Wir haben jede Konfiguration mehrfach mit HTTP, HTTPS oder HTTP/2 getestet. Die ersten beiden Konfigurationen gelten für alle drei Protokolle, Server Push hingegen nur für HTTP/2.
Das Verhalten wurde mithilfe der Chrome-Entwicklertools gemessen. Das häufigste Verhalten jeder Konfiguration wurde ausgewertet und gemittelt. Anschließend wurden die Zeiten mit der RTT der Verbindung (gemessen mithilfe von ping) korreliert, um die mechanische Wirkung der einzelnen Methoden zu veranschaulichen.

Einige grundlegende Beobachtungen
- DOM geladen bezeichnet die Zeit, die benötigt wird, um eine neue Verbindung herzustellen und die Seite demo.html abzurufen. Stylesheet bezeichnet die Zeit, die zum Abrufen der CSS-Ressource benötigt wird.
- Der Aufbau einer Verbindung über HTTP dauert 1 RTT, über HTTPS und HTTP/2 hingegen 2 RTTs.
- Die Nutzlast der HTML- und CSS-Ressourcen ist kleiner als die maximale Übertragungseinheit (MTU), sodass ein
GET-Vorgang in etwa 1 RTT abgeschlossen ist.
Interpretation der Ergebnisse: Preload-Hinweise
- Preload-Hinweise haben nur minimale Auswirkungen auf die CSS-Ressource, da sie direkt in der HTML-Ressource referenziert wird und die HTML-Ressource schnell bereitgestellt wird. Der Browser initiiert die CSS-Anfrage, sobald die HTML-Seite bereitgestellt wurde.
- Preload-Hinweise bewirken, dass der Download von Ressourcen, die in der CSS-Ressource deklariert sind (hier die beiden Bilder), schneller gestartet wird. Bei Verwendung von Preload-Hinweisen können die Downloads 1 RTT früher beginnen.
- Die Nettoeinsparung durch Preload-Hinweise kann 1 RTT oder mehr betragen. Beim parallelen Herunterladen von Ressourcen muss der Browser eine oder mehrere zusätzliche Verbindungen öffnen. Die Leistung hängt davon ab, ob langsame Anfragen (mit größeren Antworten) zuerst eingeplant oder verzögert werden, während neue Verbindungen geöffnet werden. Diese unvorhersehbare Reihenfolge der Anfragen erklärt die Beschleunigung um 1 RTT bei HTTP und HTTP/2 sowie um 2 RTT bei HTTPS.
Interpretation der Ergebnisse: Server-Push
- Server Push verbesserte die Zeit gegenüber Preload-Hinweisen um eine weitere 1 RTT. Die Push-„Antworten“ wurden gleichzeitig mit der Antwort auf die erste Anfrage initiiert, während bei den Antworten auf die Preload-Hinweise eine Verzögerung von 1 RTT entstand – 0,5 RTT für die Antwort auf die erste Anfrage plus 0,5 RTT für die Preload-
GET-Anfrage.
Testhinweise
- Für jede Konfiguration wurden mehrere Testläufe durchgeführt. Jeder Lauf begann mit einem leeren Browser-Cache und ohne bestehende Keepalive-Verbindungen zum NGINX-Server. Die NGINX-Direktiven „
keepalive_timeout“ und „http2_idle_timeout“ wurden verwendet, um Keepalive-Verbindungen schnell zu schließen. - Derzeit scheint es nicht möglich zu sein, Schriftartressourcen per Push an Chrome zu übertragen, möglicherweise aufgrund einer bekannten Komplikation. Chrome fordert eine Schriftartressource ausdrücklich an, selbst wenn sie bereits per Push übertragen wurde.
- Es wurde darauf geachtet, die Browser-Caches vor jedem Test explizit zu leeren, und alle Inhalte wurden mit abgelaufenen Cache-Control-Headern ausgeliefert.
- Chrome speichert vorab geladene Ressourcen im Cache. Diese zwischengespeicherten Ressourcen werden beim Deaktivieren des Cachings nicht immer ignoriert und auch durch das explizite Leeren des Browser-Caches nicht immer gelöscht. (In Chrome können Sie das Caching unter anderem deaktivieren, indem Sie auf der Registerkarte Cache deaktivieren im Bereich Netzwerk der Entwicklertools das entsprechende Kontrollkästchen aktivieren. Um den Browser-Cache zu leeren, können Sie bei geöffneten Entwicklertools mit der rechten Maustaste auf die Schaltfläche zum Aktualisieren des Browsers klicken und Cache leeren und vollständig aktualisieren auswählen.)
- Bei einigen Versuchen, Inhalte vorab zu laden, konnte Chrome zwischengespeicherte Kopien nicht erneut validieren und lud die Ressource anschließend regulär herunter. Diese Versuche wurden bei den Messungen nicht berücksichtigt.
- Chrome fügt allen neuen SSL-Verbindungen, die zuvor akzeptierte selbstsignierte Zertifikate verwenden, eine unnötige Verzögerung von 2 RTT hinzu. Der Test wurde mit von einer Zertifizierungsstelle signierten Let’s-Encrypt-Zertifikaten durchgeführt, um diese Verzögerung von 2 RTT zu vermeiden.
- DNS-Verzögerungen wurden durch Bearbeiten der lokalen Datei „/etc/hosts“ behoben.
- Bei diesen einfachen Tests wurde nicht versucht, die Auswirkungen von Server Push zu messen, wenn der Client bereits über eine zwischengespeicherte Kopie der Ressource verfügt. Vor jedem Test wurden alle Caches geleert, und die meisten Push-Vorgänge waren zu schnell, um sie abzubrechen.
Fazit
Dieser Test wurde bewusst einfach gehalten, um die Funktionsweise von Preload-Hinweisen und Server-Push zu verdeutlichen. In einfachen Situationen erzielt Server-Push gegenüber Preload-Hinweisen eine Verbesserung um 1 RTT und eine noch größere Verbesserung gegenüber nicht optimierten, sequenziellen GET-Anfragen und der Erkennung abhängiger Ressourcen.
Realistischere Anwendungsfälle weisen deutlich mehr Variablen auf: mehrere abhängige Ressourcen, mehrere Quellen und sogar die Möglichkeit, Bandbreite zu verschwenden, indem Ressourcen übertragen werden, die bereits im Cache vorhanden sind oder nicht sofort benötigt werden. Auch Unterschiede zwischen Browsern wirken sich auf die Leistung aus. Ihre Ergebnisse werden mit Sicherheit von denen dieses einfachen Tests abweichen.
Das Chrome-Team hat beispielsweise einige detaillierte Empfehlungen dazu veröffentlicht, wann Server Push eingesetzt werden sollte, und Messungen auf komplexeren Websites durchgeführt, um die Auswirkungen von fehlender Optimierung, Preload-Hinweisen und Server Push über HTTP/2 zu vergleichen. Der Bericht „Faustregeln für HTTP/2 Push“ ist für alle lesenswert, die den Einsatz von HTTP/2 Server Push in einer Produktivumgebung erwägen.
Die pragmatische Schlussfolgerung lautet: Wenn Sie im Voraus ermitteln können, welche Ressourcen benötigt werden, ist es durchaus von Vorteil, wenn vorgelagerte Server einen Preload-Hinweis senden. Der zusätzliche Nutzen, diese Ressourcen per Server Push zu übertragen, ist zwar gering, aber messbar. Allerdings kann dies unter Umständen zu unnötigem Bandbreitenverbrauch und Verzögerungen bei benötigten Ressourcen führen. Sie sollten daher jede Server-Push-Konfiguration sorgfältig testen und überwachen.
Anhang: Wie funktioniert HTTP/2-Push?
Die folgenden Informationen basieren zum Teil auf den Recherchen in Jake Archibalds sehr ausführlichem Blogbeitrag „HTTP/2-Push ist schwieriger, als ich dachte“.
HTTP/2 Server Push wird üblicherweise verwendet, um abhängige Ressourcen vorab zu senden, wenn der Client eine Ressource anfordert. Fordert ein Client beispielsweise eine Webseite an, kann der Server zugehörige Stylesheets, Schriftarten und Bilder an den Client übertragen.
Wenn ein Client eine HTTP/2-Verbindung herstellt, kann der Server über diese Verbindung eine oder mehrere Server-Push-Antworten initiieren. Mit diesen Pushes werden Ressourcen gesendet, die der Client nicht ausdrücklich angefordert hat.
Der Client kann einen Push entweder ablehnen (indem er einen RST_STREAM-Frame sendet) oder annehmen. Der Client speichert die per Push übertragenen Inhalte in einem lokalen „Push-Cache“, der der HTTP/2-Verbindung zugeordnet ist.
Wenn der Client später über eine bestehende HTTP/2-Verbindung eine Ressource anfordert, prüft er im Push-Cache der Verbindung, ob bereits eine vollständige oder noch laufende Antwort auf die Anfrage vorliegt. Er verwendet bevorzugt die zwischengespeicherte Ressource, anstatt eine neue HTTP/2-Anfrage für die Ressource zu stellen.
Jede per Push übertragene Ressource verbleibt im verbindungsspezifischen Push-Cache, bis sie (a) verwendet oder (b) die HTTP/2-Verbindung geschlossen wird:
- Wenn die Ressource verwendet wird, erstellt der Client eine Kopie und der Eintrag im Push-Cache wird gelöscht. Wenn die Ressource cachefähig ist, kann der Client seine Kopie anschließend im HTTP-Seiten-Cache speichern.
- Wenn die HTTP/2-Verbindung aus irgendeinem Grund geschlossen wird, wird ihr lokaler Push-Cache gelöscht.
Dies hat mehrere Auswirkungen:
- Inhalte im HTTP-Seitencache des Browsers werden gegenüber Inhalten im Push-Cache bevorzugt verwendet, selbst wenn die per Push übertragenen Inhalte aktueller sind.
- HTTP/2-Verbindungen können von verschiedenen Seitenaufrufen gemeinsam genutzt werden. Eine Ressource, die infolge eines Seitenaufrufs per Push übertragen wurde, kann verwendet werden, wenn sie bei einem anderen Seitenaufruf angefordert wird.
- Anfragen mit Anmeldedaten verwenden andere HTTP/2-Verbindungen als Anfragen ohne Anmeldedaten. Beispielsweise wird eine Ressource, die mit einer ursprungsübergreifenden Anfrage (mit Anmeldedaten) übertragen wird, möglicherweise nicht gefunden, wenn der Browser die Ressource ohne Anmeldedaten anfordert.
Eine wesentlich ausführlichere Liste der Probleme finden Sie in Jake Archibalds Blogbeitrag „HTTP/2-Push ist schwieriger als gedacht“.
HTTP/2 Server Push ist eine interessante Funktion. Testen Sie Ihre HTTP/2-Server-Push-Konfiguration unbedingt gründlich und seien Sie darauf vorbereitet, auf Preload-Hinweise zurückzugreifen, wenn diese ein besser vorhersehbares, Cache-bewusstes Verhalten ermöglichen.
Über den Autor

Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.