HTTP/2

Ce billet date de plusieurs années, ses informations peuvent être devenues obsolètes.

Ce billet fait partie d'une série en 10 volets : #1, #2, #3, #4, #5, #6, #7, #8, #9 et #10.

Notes de lecture de HTTP/2.

L'objectif du protocole HTTP/2 est de réduire la latence en permettant :

  • plusieurs échanges simultanés (multiplexage) sur la même connexion
  • une compression des en-têtes HTTP
  • la priorisation des requêtes
  • le server push

HTTP/2 ne modifie pas la sémantique HTTP (en-têtes, codes d'état etc.) mais change la façon dont les données sont formatées et transportées en introduisant une couche de segmentation (framing) binaire des données qui casse la rétrocompatibilité avec les versions précédentes d'HTTP d'où l'incrément de version majeure du protocole vers HTTP/2.

HTTP/2 est issu du protocole expérimental SPDY développé par Google.

Binary Framing Layer

Le terme "couche" (layer) fait référence à un mécanisme d'encodage situé entre l'interface des sockets et l'API HTTP exposée aux applications.

À la place des délimitations par Carriage Return Line Feed du protocole HTTP/1.x, les communications HTTP/2 sont découpées en trames (frames) binaires.

Par conséquent, client et serveur doivent utiliser un mécanisme binaire pour se comprendre et il faut un outil de type Wireshark pour inspecter et déboguer le protocole.

Streams, Messages, Frames

Toutes les communications s'effectuent via une seule connexion TCP qui peut transporter n'importe quel nombre de streams (multiplexage).

Terminologie HTTP/2 :

  • stream : un flux d'octets bidirectionnel au sein d'une connexion établie transportant un ou plusieurs messages
  • message : une séquence de frames complète qui correspond à une requête ou à une réponse
  • frame (une trame) : la plus petite unité de communication en HTTP/2, chacune contenant un en-tête identifiant a minima le stream auquel elle appartient

Une communication HTTP/2 est un échange binaire de frames formant des messages appartenant à un stream particulier.

Multiplexage des requêtes et des réponses

HTTP/1.x nécessite l'ouverture de plusieurs connexion simultanées pour améliorer les performances.

HTTP/2 permet le multiplexage des requêtes et des réponses sur une seule connexion TCP en décomposant les messages en frames qui peuvent être entrecroisées puis réassemblées.

Priorité des streams

L'ordre dans lequel les frames sont acheminées devient alors un facteur critique de performance.

Pour influer sur l'odre, HTTP/2 permet à chaque stream d'avoir un poids (entre 1 et 256) et une dépendance explicite à un autre stream.

La combinaison de ces 2 éléments permet au client de construire un arbre de priorité pour exprimer un ordre idéal dans lequel il souhaite recevoir les réponses. Le serveur peut s'en servir pour allouer les ressources de traitement (CPU, mémoire etc.).

Une connexion par origine

Une seule connexion par origine est nécessaire en HTTP/2 grâce au multiplexage. Toutes les connexions HTTP/2 sont persistantes (de longue durée).

En réutilisant la même connexion, HTTP/2 permet d'utiliser plus efficacement les connexions TCP conçues pour des connexions longue durée et du trafic volumineux.

Server Push

En HTTP/2, le serveur a la capacité d'envoyer (de pousser) plusieurs réponses pour une seule requête client.

HTTP/2 s'affranchit du format requête-réponse unique en permettant des systèmes "une requête-plusieurs réponses".

Compression des en-têtes

En HTTP/1.x, les métadonnées sont envoyées en texte brut et ajoutent de 500 à 800 octets de surcharge par transfert, et parfois plusieurs kilo-octets supplémentaires si des cookies HTTP sont utilisés.

HTTP/2 compresse les en-têtes avec le format de compression HPACK.

Mise à niveau vers HTTP/2

Le standard HTTP/2 ne nécessite pas l'utilisation de TLS, mais en pratique c'est le moyen le plus fiable de déployer un nouveau protocole en présence d'un grand nombre d'intermédiaires.

Le mécanisme recommandé est donc d'utiliser TLS avec l'ALPN pour négocier le protocole pendant la poignée de main TLS sans ajouter de latence.

Certains navigateurs ont annoncé le support d'HTTP/2 uniquement via TLS.

En dehors du navigateur, il est toujours possible d'initier une connexion HTTP/2 non sécurisée via l'en-tête HTTP Upgrade.

En-tête des trames

Une fois la connexion HTTP/2 établie, client et serveur communiquent en échangeant des frames.

Les frames transportent les données et ont un en-tête qui permet d'identifier leurs longueurs, leurs types, leurs drapeaux et leurs identificateurs de stream.

La longueur des frames étant facile à déterminer, l'analyseur peut passer à la trame suivante rapidement, une amélioration considérable des performances par rapport à HTTP/1.x.

La spécification HTTP/2 définit les types des frames : DATA, HEADERS, PRIORITY, PUSH_PROMISE etc.

Optimiser pour HTTP/2

En HTTP/2, les requêtes sont peu coûteuses et sont multiplexées.

On peut se défaire des contournements imaginés pour HTTP/1.x : domain sharding, concaténation et intégration des ressources en-ligne.

Les ressources critiques qui bloquent la construction et le rendu des pages peuvent être identifiées en amont et transmises via server push en permettant d'économiser des allers-retours.

Tous les problèmes sont-ils réglés ?

Dans les cas où le nombre de paquets perdus augmente, les performances d'HTTP/2 se dégradent considérablement à cause du Head-of-Line Blocking de TCP. Comme tous les streams partagent la même connexion TCP, l'impact peut être violent. À partir d'un certain seuil, HTTP/1.x semble mieux fonctionner :

As the packet loss rate increases, HTTP/2 performs less and less well. At 2% packet loss (which is a terrible network quality, mind you), tests have proven that HTTP/1 users are usually better off - because they typically have up to six TCP connections to distribute lost packets over.

D'autre part, à cause du nombre de requêtes simultanées envoyées par les navigateurs, la charge peut augmenter considérablement côté serveur.

HTTP/3 en cours d'élaboration a décidé d'utiliser UDP pour la couche de transport. La pari sera-t-il réussi ou bien HTTP/1.x restera-t-il un compromis tolérable ?

Pour aller plus loin

Avant HTTP/1.1 Après XMLHttpRequest

Tag Kemar Joint