La prise en charge du push serveur HTTP/2 est également incluse dans NGINX Plus R15.
Nous sommes heureux d’annoncer que NGINX 1.13.9, publié le 20 février 2018, prend en charge le push serveur HTTP/2. Pour les utilisateurs de NGINX Plus, la prise en charge du push serveur HTTP/2 sera incluse dans la prochaine version de NGINX Plus R15, dont la sortie est prévue en avril 2018.
Le push serveur, qui est défini dans la spécification HTTP/2, permet à un serveur d’envoyer de manière anticipée des ressources à un client distant, en prévision d’une éventuelle demande prochaine de ces ressources par le client. Vous pouvez ainsi réduire d’un RTT ou plus le nombre de RTT (temps d’aller-retour, c’est-à-dire le temps nécessaire à une requête et à sa réponse) lors du chargement d’une page, offrant ainsi une réponse plus rapide à l’utilisateur.
Le push serveur peut être utilisé pour fournir à l’avance à un client les feuilles de style, les images et les autres ressources dont il aura besoin pour afficher une page web. Veillez à ne pousser que les ressources nécessaires ; ne poussez pas celles que le client est susceptible d’avoir déjà mises en cache.
Dans cet article de blog, je décris :
- Configuration de base du push serveur HTTP/2
- Comment vérifier que le push serveur HTTP/2 fonctionne (à l’aide des outils du navigateur ou de
nghttp) - Envoi automatique de contenu à l’aide de l’en-tête «
Link» - Envoi sélectif de contenu
- Mesurer l’effet du push serveur HTTP/2
Configuration du Server Push HTTP/2
Pour envoyer des ressources en même temps que le chargement d’une page, utilisez la directive « http2_push » comme suit :
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;
}
}Vérification du push serveur HTTP/2
Vous pouvez facilement vérifier que le push serveur est bien actif à l’aide de l’une des deux méthodes suivantes :
- Les outils de développement de votre navigateur web
- Un client HTTP/2 en ligne de commande tel que
nghttp
Vérification à l’aide des outils de développement (Google Chrome)
Voici comment utiliser les outils de développement de votre navigateur web pour vérifier que le push serveur est bien actif, en prenant Google Chrome comme exemple. Dans la figure, la colonne « Initiateur » de l’onglet « Réseau » des outils de développement de Chrome indique que plusieurs ressources ont été envoyées au client dans le cadre d’une requête portant sur /demo.html.

Vérification avec un client en ligne de commande (nghttp)
En plus des outils intégrés aux navigateurs web, vous pouvez utiliser le client en ligne de commande « nghttp » du projet nghttp2.org pour vérifier que le push serveur est bien activé. Vous pouvez télécharger le client en ligne de commande « nghttp » depuis GitHub, ou installer le paquet correspondant à votre système d’exploitation, s’il est disponible. Pour Ubuntu, utilisez le paquet « nghttp2-client ».
Dans la sortie, l’astérisque (*) indique les ressources envoyées par le serveur via la fonctionnalité Server Push.
$ 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.jpgEnvoi automatique de ressources aux clients
Dans de nombreux cas, il est peu pratique, voire impossible, de répertorier dans le fichier de configuration NGINX les ressources que vous souhaitez envoyer aux clients. C’est pourquoi NGINX permet également d’intercepter les en-têtes de préchargement Link preload headers, puis d’envoyer les ressources qui y sont indiquées. Pour activer le préchargement, ajoutez la directive http2_push_preload à la configuration :
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;
}
}Par exemple, lorsque NGINX fonctionne comme proxy (pour HTTP, FastCGI ou d’autres types de trafic), le serveur en amont peut ajouter un en-tête Link comme celui-ci à sa réponse :
Link: </style.css>; as=style; rel=preloadNGINX intercepte cet en-tête et lance un push serveur de /style.css. Le chemin indiqué dans l’en-tête Link doit être absolu ; les chemins relatifs tels que ./style.css ne sont pas pris en charge. Le chemin peut éventuellement inclure une chaîne de requête.
Pour envoyer plusieurs objets en mode push, vous pouvez fournir plusieurs en-têtes « Link » ou, mieux encore, inclure tous les objets dans une liste séparée par des virgules :
Link: </style.css>; as=style; rel=preload, </favicon.ico>; as=image; rel=preloadSi vous ne souhaitez pas que NGINX envoie une ressource préchargée, ajoutez le paramètre nopush à l’en-tête :
# Resource is not pushedLink: </nginx.png>; as=image; rel=preload; nopushLorsque http2_push_preload est activé, vous pouvez également lancer un push serveur de préchargement en définissant l’en-tête de réponse dans votre configuration NGINX :
add_header Link "</style.css>; as=style; rel=preload";Envoi sélectif de ressources aux clients
La spécification HTTP/2 n’aborde pas la difficulté qui consiste à déterminer s’il faut ou non envoyer des ressources de manière proactive. De toute évidence, il est préférable de n’envoyer ainsi aux clients que les ressources dont ils auront probablement besoin et qu’ils ont peu de chances d’avoir déjà en cache.
Une approche possible consiste à envoyer les ressources aux clients uniquement lors de leur première visite sur le site. Vous pouvez, par exemple, vérifier la présence d’un cookie de session et définir conditionnellement l’en-tête « Link », afin que les ressources ne soient préchargées que si le cookie de session est absent.
En supposant que les clients se comportent correctement et incluent le cookie dans les requêtes suivantes, la configuration ci-dessous permet à NGINX de n’envoyer les ressources aux clients qu’une seule fois par session de navigateur :
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";
}Mesurer l’impact du push serveur HTTP/2
Pour mesurer l’effet du push serveur, nous avons créé une page de test simple, /demo.html, qui fait référence à une feuille de style distincte, /style.css. Cette feuille de style fait elle-même référence à deux images. Nous avons testé les temps de chargement de la page avec trois configurations différentes :
- Requêtes
GETséquentielles (sans optimisation) – Le navigateur chargeait les ressources lorsqu’il détectait qu’elles étaient nécessaires - Indications de préchargement – Des indications de préchargement (
Linkheaders) ont été incluses dans la première réponse pour indiquer au navigateur de charger les dépendances - Push serveur (HTTP/2 uniquement) – Les dépendances étaient envoyées de manière anticipée au navigateur

Nous avons effectué plusieurs séries de tests pour chaque configuration avec HTTP, HTTPS ou HTTP/2. Les deux premières configurations s’appliquent aux trois protocoles, tandis que le push serveur s’applique uniquement à HTTP/2.
Le comportement a été mesuré à l’aide des outils de développement de Chrome. Le comportement le plus courant de chaque configuration a été évalué et moyenné, et les temps ont été corrélés au RTT de la liaison (mesuré à l’aide de ping) afin d’illustrer l’effet mécanique de chaque méthode.

Quelques observations de base
- Chargement du DOM correspond au temps nécessaire pour établir une nouvelle connexion et récupérer la page demo.html. Feuille de style correspond au temps nécessaire pour récupérer la ressource CSS.
- L’établissement d’une connexion via HTTP nécessite 1 RTT ; via HTTPS et HTTP/2, il en nécessite 2.
- La charge utile des ressources HTML et CSS est inférieure à la taille de l’unité de transmission maximale (MTU), de sorte qu’une opération
GETs’effectue en environ 1 RTT.
Interprétation des résultats : indications de préchargement
- Les indications de préchargement ont un effet minime sur la ressource CSS, car celle-ci est directement référencée dans la ressource HTML, qui est transmise rapidement. Le navigateur lance la requête CSS dès que la page HTML est transmise.
- Les indications de préchargement permettent effectivement de lancer rapidement le téléchargement des ressources déclarées dans la ressource CSS (ici, les deux images). Les téléchargements peuvent démarrer 1 RTT plus tôt lorsque des indications de préchargement sont utilisées.
- Le gain net obtenu grâce aux indications de préchargement peut atteindre 1 RTT ou plus. Lors du téléchargement de ressources en parallèle, le navigateur doit ouvrir une ou plusieurs connexions supplémentaires. Les performances varient selon que les requêtes lentes (réponses plus volumineuses) sont traitées en premier ou retardées pendant l’ouverture de nouvelles connexions. Cet ordre imprévisible des requêtes explique le gain de 1 RTT pour HTTP et HTTP/2, et de 2 RTT pour HTTPS.
Interprétation des résultats : push serveur
- Le push serveur a encore amélioré de 1 RTT le temps obtenu avec les indications de préchargement. Les « réponses » push ont été lancées en même temps que la réponse à la première requête, tandis que les réponses aux indications de préchargement ont subi un délai de 1 RTT : 0,5 RTT pour la réponse à la première requête, plus 0,5 RTT pour la requête de préchargement
GET.
Notes sur les tests
- Plusieurs séries de tests ont été effectuées pour chaque configuration. Chaque série a commencé avec un cache de navigateur vide et sans aucune connexion persistante établie avec le serveur NGINX. Les directives NGINX «
keepalive_timeout» et «http2_idle_timeout» ont été utilisées pour fermer rapidement les connexions persistantes. - À l’heure actuelle, il ne semble pas possible d’envoyer de manière proactive des ressources de police à Chrome, peut-être en raison d’une complication connue. Chrome envoie une requête explicite pour une ressource de police, même si celle-ci lui a déjà été envoyée de manière proactive.
- Nous avons pris soin de vider explicitement le cache du navigateur avant chaque test, et tous les contenus ont été servis avec des en-têtes de contrôle du cache expirés.
- Chrome met en cache les ressources préchargées. Ces ressources mises en cache ne sont pas systématiquement ignorées lorsque vous désactivez la mise en cache, ni systématiquement supprimées lorsque vous effectuez explicitement l’opération « vider le cache du navigateur ». (Dans Chrome, vous pouvez notamment désactiver la mise en cache en cochant la case Désactiver le cache dans l’onglet Réseau des outils de développement. Pour vider le cache du navigateur, faites un clic droit sur le bouton d’actualisation du navigateur lorsque les outils de développement sont ouverts, puis sélectionnez Vider le cache et effectuer une actualisation forcée).
- Certaines tentatives de préchargement de contenu ont conduit Chrome à essayer, sans succès, de revalider les copies mises en cache, avant de télécharger normalement la ressource. Ces tentatives n’ont pas été prises en compte dans les mesures.
- Chrome ajoute un délai inutile de 2 RTT à toutes les nouvelles connexions SSL qui utilisent des certificats autosignés précédemment acceptés. Le test a été réalisé avec des certificats Let’s Encrypt signés par une autorité de certification afin d’éviter ce délai de 2 RTT.
- Les délais liés au DNS ont été éliminés en modifiant le fichier local /etc/hosts.
- Ces tests simples n’ont pas cherché à mesurer l’effet du push serveur lorsque le client dispose déjà d’une copie de la ressource dans son cache. Lors des tests, tous les caches ont été vidés avant chaque essai, et la plupart des pushs étaient trop rapides pour pouvoir être annulés.
Conclusion
Ce test a été volontairement simplifié afin de mettre en évidence le fonctionnement des indications de préchargement et du push serveur. Dans les situations simples, le push serveur permet de gagner 1 RTT par rapport aux indications de préchargement, et offre un gain encore plus important par rapport aux requêtes GET séquentielles non optimisées et à la découverte des ressources dépendantes.
Les cas d’usage plus réalistes comportent bien davantage de variables : plusieurs ressources dépendantes, plusieurs sources, voire un risque de gaspillage de bande passante lorsque des ressources déjà mises en cache ou dont l’utilisation n’est pas immédiate sont envoyées en mode push. Les différences entre les navigateurs ont également une incidence sur les performances. Les résultats obtenus seront certainement différents de ceux de ce test simple.
Par exemple, l’équipe Chrome a publié des recommandations détaillées sur les situations dans lesquelles utiliser le push serveur et a effectué des mesures sur des sites plus complexes afin de comparer les effets de l’absence d’optimisation, des indications de préchargement et du push serveur via HTTP/2. Son rapport « Règles générales pour le push HTTP/2 » mérite d’être lu par toute personne envisageant de déployer le push serveur HTTP/2 en production.
La conclusion pragmatique est que, si vous pouvez déterminer à l’avance quelles ressources seront nécessaires, il est réellement avantageux que les serveurs en amont envoient une indication de préchargement. Le gain supplémentaire apporté par l’envoi proactif de ces ressources est faible, mais mesurable. Il peut toutefois entraîner un gaspillage de bande passante et retarder le chargement des ressources nécessaires. Vous devez tester et surveiller attentivement toute configuration d’envoi proactif par le serveur.
Annexe : comment fonctionne le push HTTP/2 ?
Les informations ci-dessous s’appuient en partie sur les recherches présentées dans l’article de blog très détaillé de Jake Archibald, « Le push HTTP/2 est plus complexe que je ne le pensais ».
Le push serveur HTTP/2 est généralement utilisé pour envoyer de manière anticipée des ressources dépendantes lorsqu’un client demande une ressource. Par exemple, si un client demande une page web, le serveur peut lui envoyer de manière proactive les feuilles de style, les polices et les images dont elle dépend.
Lorsqu’un client établit une connexion HTTP/2, le serveur peut choisir d’initier une ou plusieurs réponses push sur cette connexion. Ces envois transmettent des ressources que le client n’a pas explicitement demandées.
Le client peut soit refuser un envoi push (en envoyant une trame « RST_STREAM »), soit l’accepter. Le client stocke le contenu envoyé dans un « cache push » local associé à la connexion HTTP/2.
Par la suite, lorsque le client demande une ressource via une connexion HTTP/2 établie, il vérifie dans le cache push de la connexion si une réponse à cette requête est déjà complète ou en cours de transfert. Il utilise en priorité la ressource mise en cache plutôt que d’envoyer une nouvelle requête HTTP/2 pour cette ressource.
Toute ressource envoyée en mode push reste dans le cache push propre à la connexion jusqu’à ce que (a) elle soit utilisée ou (b) la connexion HTTP/2 soit fermée :
- Si la ressource est utilisée, le client en récupère une copie et l’entrée correspondante est supprimée du cache push. Si la ressource peut être mise en cache, le client peut alors placer sa copie dans le cache HTTP de la page.
- Si la connexion HTTP/2 est fermée pour une raison quelconque, son cache push local est supprimé.
Cela a plusieurs implications :
- Le contenu du cache de pages HTTP du navigateur est utilisé en priorité par rapport à celui du cache push, même si le contenu transmis par push est plus récent.
- Les connexions HTTP/2 peuvent être partagées entre différents chargements de page. Une ressource envoyée en mode push lors du chargement d’une page peut être utilisée lorsqu’elle est demandée au cours du chargement d’une autre page.
- Les requêtes avec des informations d’identification utilisent des connexions HTTP/2 différentes de celles des requêtes sans informations d’identification. Par exemple, une ressource envoyée de manière proactive à la suite d’une requête interorigine (avec informations d’identification) risque de ne pas être trouvée si le navigateur effectue une requête sans informations d’identification pour cette ressource.
Vous pouvez consulter une liste bien plus détaillée des problèmes dans l’article de blog de Jake Archibald intitulé « Le push HTTP/2 est plus compliqué que je ne le pensais ».
Le push serveur HTTP/2 est une fonctionnalité intéressante. Veillez à tester minutieusement votre configuration de push serveur HTTP/2 et soyez prêt à vous rabattre sur les indications de préchargement lorsque celles-ci offrent un comportement plus prévisible et tenant compte du cache.
À propos de l’auteur

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.
Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.
Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.
Caches partagés avec les clusters de cache NGINX Plus, partie 1
Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.
Introduction aux microservices
Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.