Analyse d’une requête HTTP – serveur et réseau

On parle de temps, de performance, mais finalement que mesure t-on ? La question n’est pas inutile puisque pour une même requête il y a bien trois étape visibles du point de vue du visiteur, cinq du point de vue du navigateur et autant pour le serveur. Alors, que mesure t-on ?

Je vous propose un petit schéma incomplet des interactions lors de la requête d’une page HTML (attention, aucune échelle ou proportion n’est respectée).

Alors, vous mesurez quoi ?

La requête DNS

Une fois que le visiteur clique sur un lien, c’est une requête DNS qui est lancée par le navigateur et environ 30ms qui sont perdues, parfois même jusqu’à 100 ou 150ms (triangle gris sur le schéma). Microsoft Internet Explorer 6 cache cette information pendant 30 minutes mais les autres navigateurs la relancent plus souvent. Mozilla Firefox ne garde le résultat de la requête DNS que pour une petite minute. Vous l’aurez donc quasiment à chaque nouvelle page. Vous pouvez réduire l’influence des requêtes DNS en limitant le nombre de domaines et sous-domaines utilisés par votre site. Gardez le nombre de domaines en dessous de quatre.

La connexion au serveur

L’étape suivante c’est l’établissement de la connexion avec le serveur que vous souhaitez joindre (triangle vers sur le schéma). C’est assez rapide mais ça reste quelque chose qui va impacter les performances. Autorisez le keep-alive pour les ressources statiques (images, feuilles de styles, javascript) : Le navigateur et le serveur vont réutiliser la connexion existante au lieu de rétablir une nouvelle connexion pour chaque composant. Le gain est notable, j’en avais déja parlé.

Maintenant le keep-alive c’est aussi ce qui va garder la connexion ouverte inutilement une fois que vous aurez téléchargé tous les composants. C’est le rectangle vert en bas sur le schéma. C’est coûteux pour vs serveurs. Désactivez donc le keep-alive sur le serveur qui renvoie les pages HTML, et réduisez la valeur pour les autres : cinq secondes sont bien suffisantes.

La requête HTTP elle-même, et l’attente qui suit

Vient ensuite la requête HTTP elle-même (parallélogramme jaune sur le schéma). Vous voyez qu’elle prend un certain temps, symbolisée par une épaisseur sur le schéma. En cumulant toutes les entêtes et un cookie classique, votre requête peut facilement prendre 1ko. Pensez donc à réduire la taille du cookie, et même à ne pas avoir de cookie pour les ressources statiques en les mettant sur un domaine tiers.

Par la suite, pour réduire l’influence des requêtes HTTP, il ne reste plus qu’à en faire moins. En fait c’est assez simple. Il suffit d’aggréger plusieurs fichiers en un seul, qu’on parle de CSS et javascript, ou de sprites pour les images. Vous épargnez le temps de faire la requête, mais aussi tout le temps d’attente du navigateur entre la fin de la requête et la réception de la réponse (espace blanc entre les parallélogrammes bleus et jaunes sur la ligne de temps du navigateur).

Une autre possibilité c’est d’envoyer plusieurs requêtes HTTP coup sur coup sans attendre les réponses. On utilise alors au mieux cet espace inutile entre la fin de la requête et le début de la réponse. On se permet même d’envoyer des donner dans un sens pendant qu’on en reçoit de l’autre côté, donc superposer des requêtes jaunes dans mon schéma avec des réponses bleues. C’est ce qui est réalisé avec le pipelining HTTP.

Le calcul de la page par le serveur

Voilà la mesure du diable. Dès qu’on parle de performance tout le monde va vite mesurer ce temps de génération des pages, en mauve sur le schéma. Même si l’échelle et les proportions ne sont pas respectées sur le schéma, il est évident que cette mesure n’est vraiment pas la a seule, ni même la plus importante. Pour des pages bien faites et des serveurs qui ne sont pas surchargées, il est très rare d’avoir des pages qui prennent plus de 100ms pour le calcul serveur. C’est généralement dix fois moins, alors que le chargement complet de la page pour le visiteur prend lui plusieurs secondes.

Mais surtout, c’est létape qui est souvent la première à être optimisée, et celle où il est assez complexe de gagner encore des performances si on a déjà penser au cache. Ne vous focalisez pas sur le temps de génération des pages, sauf s’il est flagrant qu’il est disproportionné par rapport aux besoins.

Éventuellement, si votre page peut mettre longtemps à se générer et que c’est facile à faire, vous pouvez forcer un vidage du tampon au milieu de la génération de la page, pour que l’utilisateur commence à voir le contenu réel de la page et télécharge les composants tiers pendant que le calcul de la page continue à se faire. L’équipe Performance de Yahoo! en parle, l’équipe Search aurait eu de bons résultats avec cette technique.

Le téléchargement de la page

La dernière étape du point de vue du serveur c’est le téléchargement de la page elle-même. C’est un des postes qui impactent le plus les performances. On a beau faire des publicités pour des liaisons à 24mb/s, si vous téléchargez une pages HTML à 2mb/s c’est bien. Et derrière si on compte les images, les cookies, les javascript, les feuilles de style, le flash, les vidéo, et la page HTML elle-même, ça prend du temps, incompressible.

Enfin certaines choses sont incompressibles, d’autres justement… vous pouver minimiser les javascript et CSS, mais aussi utiliser la compression HTTP pour tout ce qui est fichier texte (HTML, javascript, CSS, XML, Json, etc.). Les résultats sont spectaculaires et il est facile de diviser le poids par dix, donc le temps de téléchargement d’autant.

On peut aussi faire bien mieux, et réduire tout le téléchargement de la page à quelques octets. Il s’agit simplement de repérer quand le navigateur a déjà une page similaire en cache, et de lui répondre un code HTTP 304 « la page n’a pas changée ». Ca fonctionne à base d’ETag, de date de modification et de requête conditionnelle HTTP. 

Et entre le visiteur et son navigateur ?

Je n’ai parlé que de la partie basse du schéma, en oubliant tout ce qu’il se passe entre le navigateur et l’humain derrière son écran. Ca a l’air plus simple parce qu’il y a moins de composants en jeu, mais c’est là que se passe une bonne partie des problèmes de performance, et pas forcément les plus simples à gérer.

On en parlera dans un prochain billet, vous voulez bien ?

En attendant retenez : 

  • Le début du rendu du navigateur ne correspond pas avec le début de la réception de la page HTML.
  • La fin l’interprétation du HTML ne correspond pas du tout avec la fin de la réception de la page HTML.
  • La fin du rendu total de la page peut intervenir plusieurs secondes après la fin de la réception de la page HTML.

Mais de toutes façons le jeu c’est le plus possible d’éviter tout le schéma en lui même : réduire le nombre de requêtes HTTP, soit par une réduction du nombre de composants, soit par une exploitation au mieux du cache.

Publié par edaspet

Plus d'informations sur mon profil en ligne

8 réponses sur « Analyse d’une requête HTTP – serveur et réseau »

  1. « Ne vous focalisez pas sur le temps de génération des pages »
    Oui, enfin, attention, car c’est tout de même le seul moment qui charge le serveur. Donc si c’est pas optimisé, sous la charge, cette partie va avoir tendance à bien s’allonger sur le schéma…

  2. Vous décrivez assez bien la problématique des temps de réponses, mais vous négliger les problèmes liés au une architecture multi serveurs. En effet le ETag est à proscrire sauf si ce dernier est identique sur tous les serveurs.
    Or apache par défaut utilise l’inode du fichier pour générer cet ETag et cet inode est différent sur les serveurs du parc.
    Il est donc préférable de désactiver les ETag.

    Vous pourriez également expliquer la différence entre le cache control et le Expires. Le cache control va générer un requète du navigateur vers le site, alors que le Expires ne va pas générer de requète tant que sa valeur n’a pas expiré…

  3. @Antoine: Le blog complet est dédié à la question des performances. Il comporte bien d’autres bilets, généralement chacun sur un point précis. Ce billet est là uniquement pour décrire ce qu’il se passe sur le réseau. Le reste des discussions est dispatché sur les autres contenus. Je vous invite à parcourir le reste des archives et vous inscrire au flux RSS.

    Pour la question des ETags par exemple : http://performance.survol.fr/2008/06/desactiver-les-etags/

    Pour le Cache-Control il est vrai que je n’ai pas fait de billet dédié encore à cette question. J’en parle donc en même temps partout et nulle part. C’est par exemple abordé dans ma dernière intervention au WaSP Café, sur les slides http://performance.survol.fr/2008/09/presentation-au-w3cafe/

    Par contre je me permet de vous contredire, le Cache-Control avec une directive max-age et sans le drappeau must-revalidate a le même effet que la directive Expires. L’un vient du HTTP 1.1 et l’autre du HTTP 1.0 et la forme diffère un peu, mais les deux ont la même force. Dans les deux cas le navigateur est informé de ne plus faire de requête réseau tant que le contenu n’a pas expiré.

    Promis je fais un billet bientot pour expliquer tout ça. Comme tout le temps, on pinaille sur des détails et au final on oublie de parler des bases.

  4. Merci pour ces explications.
    Je suis novice dans la matiere, je gere pourtant un site web !!!
    Pour m’aider j’utilise Netvigie qui me permet d’avoir cette décomposition et comprendre d’ou vient l’erreur, mais je pige mieux les differentes couches.

    Est ce qu on peut gere le timeout du navigateur avant qu’il declare l erreur ?

Les commentaires sont fermés.