Accélérer la navigation sur le web en 3G

Vincent Bernat

Mon portable disposant d’une connectivité 3G, j’ai décidé de prendre l’abonnement le plus économique possible sans que celui-ci soit limité en temps. J’ai finalement opté pour un abonnement à 10 € pour 250 Mio par mois chez SFR.

Proxy transparent et optimisant selon SFR#

En naviguant un peu sur le site Le Monde, j’ai remarqué que certaines requêtes étaient destinées à des IP du type 10.141.0.4. J’ai regardé rapidement avec les outils adéquats de Chromium (onglet « Réseau ») ce que cela signifiait. Toutes les images étaient servies depuis l’IP en question. Un proxy transparent (repérable à l’entête Via qu’il ajoute) avait réécrit les balises <img>. Les images ainsi servies étaient identiques aux originales pour les plus petites ou de qualité réduite pour les autres.

Les balises <style> et <script> recevait également un traitement de choc quand elles pointaient sur des ressources externes : le contenu était reporté à l’intérieur du fichier HTML. Avant :

<script src="http://s1.lemde.fr/js/lib/jquery/1.5.1/jquery.js"></script>

Après :

<script oldSrc="http://s1.lemde.fr/js/lib/jquery/1.5.1/jquery.js" NG="replaced">
/*!
 * jQuery JavaScript Library v1.5.1
 *
 * Copyright 2011, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 * […] */
</script>

Cela signifie que si un site fait appel à jQuery, une bibliothèque JavaScript très populaire, on se retrouve à télécharger l’intégralité du code dans chacune des pages, soit un surpoids de 85 Kio !

Tous les navigateurs modernes supportent les connexions HTTP persistantes qui permettent de demander plusieurs ressources au sein d’une même requête, ce qui est fort utile dès que la latence augmente un peu. Il y a alors deux cas possibles :

  1. Si la ressource est servie depuis le même serveur que la page HTML, il est possible d’utiliser la même connexion pour obtenir celle-ci, bien qu’il est possible qu’une nouvelle connexion soit ouverte pour continuer à charger le reste du document, dans ce cas, on se retrouve dans le second cas (certains navigateurs négocient par avance cette connexion supplémentaire pour l’utiliser ensuite sans aucun coût supplémentaire). On obtient donc un résultat similaire à l’inclusion dans la page mais on peut utiliser le cache du navigateur pour économiser la bande passante. Une pénalité de 100 ms est toutefois à observer étant donné que le navigateur doit demander la resource supplémentaire.

  2. Si la ressource provient d’un autre serveur (comme dans l’exemple ci-dessus), le navigateur va ouvrir une nouvelle connexion en parallèle. Cela va induire un coût d’environ 300 ms (pour une connexion 3G) afin d’établir cette nouvelle connexion TCP. Ces 300 ms sont incroyablement moins coûteuses que les 2 secondes nécessaires pour retélécharger 85 Kio à chaque requête ! De plus, les autres ressources statiques sont sans doute téléchargées depuis ce serveur et cette connexion ne sera donc pas perdue. Il est même probable qu’elle ait été nécessaire de toute façon (pour télécharger les images par exemple).

Mise à jour (06.2011)

Dans une version précédente, j’avais mélangé le mécanisme de connexions persistantes avec le pipelining. Le premier permet de réutiliser une connexion TCP existante mais chaque requête doit être émise l’une derrière l’autre et doit attendre la réponse correspondante. Le second permet d’envoyer plusieurs requêtes sans attendre les réponses. Comme indiqué par Éric Daspet dans un commentaire, le pipelining est en fait désactivé par défaut sur la plupart des navigateurs. Toutefois, les connexions persistantes sont bien supportées.

En cherchant un peu sur le web avec les mots clefs oldSrc et NG="replaced", on ne trouve pas grand chose sur le sujet. Au passage, il semblerait de plus que cette technique casse certains composants, comme TinyMCE, qui reposent sur la connaissance de leur emplacement pour télécharger les ressources supplémentaires dont ils ont besoin. SFR utiliserait un produit de Flash Networks appelé Harmony Gateway. J’ai demandé au service client des renseignements supplémentaires, notamment s’il était possible de débrayer cette fonctionnalité. Je n’ai à ce jour pas obtenu de réponse.

En essayant un peu plus tard, je me suis rendu compte que la réécriture du JavaScript n’avait plus lieu. Par contre, les images étaient toujours servies depuis un serveur tiers. Le lendemain, un autre essai m’a conduit à constater que le proxy transparent avait disparu (plus d’entête Via). Étant donné que chaque essai a été effectué à un endroit différent, il est possible que les serveurs soient installés au plus près de l’abonné et que leurs configurations soient différentes. Une autre explication est que SFR a désactivé cette fonctionnalité pour moi, sans m’en avertir.

Configuré correctement, un tel accélérateur pourrait être proposé en option par défaut aux abonnés. La plupart apprécieront le gain de vitesse procuré par un tel équipement et ceux qui se soucient de la neutralité du net pourront désactiver cette option. Bien sûr, il faut que celle-ci soit mise en avant de manière correcte, par exemple en la présentant comme une option gratuite rattachée au forfait.

Mettre en place son propre proxy optimisant#

Google fournit mod_pagespeed, un logiciel pour optimiser un site web à la volée. Il s’agit d’un module pour Apache destiné à optimiser un unique site web. Cependant, comme Apache peut agir en tant que serveur mandataire (avec mod_proxy), il est possible de mettre en place mod_pagespeed pour n’importe quel site.

Ce n’est pas très compliqué à configurer, à condition de se contenter d’une version précompilée de mod_pagespeed. Téléchargez mod_pagespeed. J’ai opté pour la version Debian 64-bit.

# touch /etc/default/mod-pagespeed
# dpkg -i ~/download/mod-pagespeed-beta_current_amd64.deb
Selecting previously deselected package mod-pagespeed-beta.
(Reading database ... 277699 files and directories currently installed.)
Unpacking mod-pagespeed-beta (from .../mod-pagespeed-beta_current_amd64.deb) ...
dpkg: dependency problems prevent configuration of mod-pagespeed-beta:
 mod-pagespeed-beta depends on apache2.2-common; however:
  Package apache2.2-common is not installed.
dpkg: error processing mod-pagespeed-beta (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 mod-pagespeed-beta
# apt-get install -f
[…]
Unpacking apache2.2-common (from .../apache2.2-common_2.2.19-1_amd64.deb) ...
Processing triggers for man-db ...
Setting up apache2.2-common (2.2.19-1) ...
[…]
# apt-get install apache2-mpm-worker
[…]
Unpacking apache2-mpm-worker (from .../apache2-mpm-worker_2.2.19-1_amd64.deb) ...
Setting up apache2-mpm-worker (2.2.19-1) ...
Starting web server: apache2.
# a2enmod proxy_http
Considering dependency proxy for proxy_http:
Enabling module proxy.
Enabling module proxy_http.
To to activate the new configuration, you need to run:
  /etc/init.d/apache2 restart

Il faut ensuite modifier le fichier /etc/apache2/mods-enabled/proxy.conf:

ProxyRequests On
<Proxy *>
    AddDefaultCharset off
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1
</Proxy>

Étant donné que placer le proxy sur le portable n’est pas très utile (vous ne voulez pas rapatrier la version non optimisée du site web à travers votre lien 3G), il faudrait installer tout ceci sur un autre serveur et autoriser le portable à l’utiliser comme proxy. Cependant, nous gardons cet exemple simpliste à titre d’illustration.

Il faut également modifier /etc/apache2/mods-enabled/pagespeed.conf pour ajouter la directive ModPagespeedDomain * et ainsi autoriser mod_pagespeed à réécrire n’importe quelle page. Redémarrez Apache quand tout est fini et vérifiez que tout fonctionne correctement :

$ curl -six http://localhost:80 http://www.lemonde.fr/ | grep ^X-Mod-Pagespeed
X-Mod-Pagespeed: 0.9.17.7-716

Parfait ! Essayons maintenant de nous rendre sur un site assez simple, comme Debian Backports. Il sert une page HTML avec deux feuilles de style :

Debian Backports sans optimisation
Debian Backports sans optimisation

On a téléchargé les trois fichiers pour un total de 8 Kio, compression comprise. Passons désormais par notre proxy :

Debian Backports avec optimisation
Debian Backports avec optimisation

mod_pagespeed a diminué la taille du fichier HTML mais a surtout combiné les deux fichiers CSS dont la taille globale a été réduite en les minifiant. Il semble qu’un bug dans Chromium fausse l’affichage de la quantité de données transférées quand on passe par un proxy. J’ai vérifié avec Wireshark que Chromium reçoit bien des données compressées pour environ 8 Kio. Le gain est assez ténu mais il devrait être meilleur sur des sites plus complexes.

Naviguer sur Internet avec mod_pagespeed ne semble pas poser de problèmes particuliers. Il semblerait donc qu’il s’agisse d’une solution viable. Un bémol cependant : il n’optimise que les pages qu’il a placées dans son cache. Cela signifie que la première fois que l’on demande une page, on dispose d’une version non optimisée. J’ignore s’il s’agit d’un comportement normal.