lundi 26 novembre 2012

Chrome ne réspecte plus les Keep-alive timeout

Il y a quelques jours j'ai eu l'occasion de faire un peu de debug réseau, à chaque fois je suis surpris par la créativité des éditeurs de nos navigateurs préférés. Chaque nouvelle version apporte de nouvelles choses au niveau de la gestion des connections afin d'améliorer encore la rapidité coté navigateur mais qu'il faut ensuite gérer coté serveur.

La dernière innovation de Chrome est le choix de garder des connexions ouvertes vers le serveur pendant très longtemps (plusieurs dizaines de minutes) au mépris de la durée de timeout spécifiée par le serveur.

Tout d'abord un petit rappel :

Que disent les spécifications ?

Les navigateurs communiquent avec les serveurs via des connexions TCP.
Encore aujourd'hui, deux versions de la spécifications cohabitent HTTP/1.0 et HTTP/1.1 bien que le premier soit des moins en moins utilisé.

En HTTP/1.0 tout était simple : quand l'utilisateur chargeait une page, le navigateur ouvrait une nouvelle connexion vers le serveur, envoyait la requête, le serveur envoyait la réponse et fermait la connexion.
Problème : l'ouverture d'une nouvelle connexion pour chaque fichier téléchargé prend du temps car ouvrir la connexion nécessite l'échange de 3 paquets réseau (en https c'est même beaucoup plus). Le chargement d'une page complète qui contient beaucoup d'éléments (images, css...) est lent.

En HTTP/1.1 a été inventé le Keep-alive : le navigateur peut demander au serveur via un en-tête HTTP  à garder la connexion ouverte pour la réutiliser pour plusieurs requêtes successives.

Connection: Keep-Alive

Le serveur indique alors par un autre en-tête s'il accepte et si oui sous quelles conditions (durée maximale d'inactivité de la connexion et nombre maximal de requêtes à envoyer par la même connexion).

Keep-Alive: timeout=10, max=5

La spécification indique aussi le nombre maximum de connexions qu'un navigateur à le droit d'ouvrir vers un serveur : 2

Par exemple pour télécharger une page qui contient 20 ressources (images, css, scripts) :

  • un navigateur HTTP/1.0 va ouvrir 20 connections successives qui vont être refermées immédiatement
  • un navigateur HTTP/1.1 va ouvrir 2 connections qu'il va garder ouvertes jusqu'à avoir chargé tous les fichiers et même 10 s de plus (timeout) au cas ou la page charge encore des fichier ou si l'utilisateur navigue sur une autre page.
Le HTTP/1.1 est donc plus rapide pour l'utilisateur. La seule contrainte est la présence de connexion avec une durée de vie plus longue qu'il faut gérer coté client et coté serveur.

En pratique que font les navigateurs

Au départ les éditeurs des navigateurs ont joué le jeu et respecté les spécification HTTP/1.1 à la lettre pour profiter des améliorations de performances mais assez rapidement ils ont voulu aller plus loin en ouvrant plus de connexions en parallèle, d'abord 4 puis parfois 12 ou plus dans les dernières versions !

Google Chrome vient d'aller encore un cran plus loin en ne respectant plus le timeout spécifié par le serveur.
En pratique Chrome va ouvrir plusieurs connexions (a priori jusqu'à 6) mais au lieu de les refermer après le timeout, il va les conserver tant que l'utilisateur garde une fenêtre ouverte sur le site. Selon le système d'exploitation, il va même tenter des les maintenir en vie en envoyant des paquets vides à intervalle régulier.

Ces nouveaux comportements sont à prendre en considération lorsqu'on configure une serveur ou qu'on suit ses performances puisque désormais on va avoir des connexions avec une durée de vie très longue et ce même si les clients n'envoient aucune requête au serveur.



Aucun commentaire: