Les problèmes de montée en charge sont choses courantes pour un site ou une application web une fois atteint un certain succès. Ces derniers sont bien trop souvent négligés, généralement jusqu’au jour où se trouve atteinte la limite critique entre l’inconfort et l’instabilité. Le trend actuel veut qu’il soit à la fois plus simple et moins cher de rajouter des machines que de reprendre son code en profondeur pour l’optimiser. Encore faut-il que l’application permette un redimensionnement de ce genre sans rentrer dans une phase de refactoring complet. Évidemment, avant d’en arriver à une solution aussi lourde, il vaut mieux s’assurer que tout a été fait pour exploiter au mieux les ressources disponibles, et cela passe notamment par un peu d’optimisation côté serveur.

Les quelques conseils distillés dans cet article ne s’appliquent pas à n’importe quel type de site web, ne les prenez donc pas pour parole d’évangile avant de vous assurer que vous rentriez bien dans la cible visée. Ils visent à améliorer les points suivants :

  • Côté applicatif, limiter au maximum les calculs faisant intervenir le processeur et les accès disques, en évitant au maximum les modifications.
  • Limiter les accès disques pour les contenus statiques à servir.
  • Économiser un peu de bande passante quand cela n’implique pas de mettre le processeur à genoux.

Cet article fonctionne exactement comme le rapport Attali : si vous en retirez un seul point, ou que vous retirez celui-ci de son contexte, vous risquez non seulement de ne pas atteindre le but espéré, mais également de vous retrouver avec le contraire de ce à quoi vous vous attendiez.

Rendez votre contenu statique

Si votre application vous le permet, rendez un maximum de contenu statique, le mieux étant de créer de simples pages HTML qui seront appelées par défaut si elles existent et générées dans le cas contraire. La majorité des CMS et des blogware le font, pour les autres, vous pouvez utiliser caches_page en Ruby on Rails, ou Skycache en PHP. L’intérêt d’une telle démarche est évidente : la présence de tels fichiers statiques sur le disque évite toute requête à votre application, Apache servant directement le contenus.

Concatenez vos fichiers CSS, Javascript et vos images CSS

Afin d’économiser les requêtes HTTP, concatenez vos fichiers CSS et vos fichiers Javascript entre eux. Cela n’est cependant pas toujours possible. Il n’est par exemple pas possible d’assembler Prototype et Scriptaculous. Outre l’économie de requêtes HTTP sur des fichiers de très petite taille, cela nous sera utile un peu plus tard.

Assemblez également vos images CSS, particulièrement les pictogrammes et les modifications onmouseover / onmouseout. Au lieu de remplacer l’image de fond, il vous suffit alors de la positionner avec background-position. Vous faites ici des économies non seulement de requêtes, mais également d’accès disques.

Mettez vos sessions en cache avec memcached

Memcached est un système de cache très générique dans lequel les objets sont placés en mémoire. Il a été créé afin d’optimiser les applications web en allégeant la charge des bases de données. Cette partie s’adresse aux utilisateurs de Ruby on Rails. J’imagine que la manipulation est également possible en PHP, mais j’avoue ne pas m’y être penché pour l’instant, même si ça risque d’arriver sous peu.

Il existe trois manières de socker les sessions coté serveur :

  1. Sur le système de fichiers, par exemple dans /tmp.
  2. Dans la base de données.
  3. En Ram, grâce à memcache.

Dans un premier temps, installez memcached sur votre système.

    # aptitude install memcached
    # /etc/init.d/memcached start
</publish:code>

Puis, installez la gem memcache-client, ou mieux, incluez-la dans votre application si vous comptez la redistribuer :

<publify:code lang="bash">
    # gem install memcache-client

Enfin, éditez votre fichier config/environment.rb afin d’y ajouter les lignes suivantes :

require 'memcache-client'
config.action_controller.session_store = :mem_cache_store

Redémarrez vos processus CGI, vous y êtes. Vous venez d’économiser un nombre conséquent d’accès disques ou de requêtes sur votre base de données. Bravo !

Mettez les éléments en cache avec mod_expires

Mod_expires est un module Apache bien pratique qui ajoute une date d’expiration dans les en-têtes HTTP de vos fichiers. Il est à utiliser sans modération sur les fichiers qui ne changent pas, ou très peu. Vous l’appliquerez donc à vos images, qu’elles soient dans le contenu ou CSS, à vos feuilles de style, vos fichiers javascript, et éventuellement vos PDF.

Activer mod_expires est très simple :

    # a2enmod expires

Ajoutez ensuite les lignes suivantes soit dans le fichier expires.conf si vous souhaitez l’activer sur l’ensemble du site, soit dans le fichier de description de votre vhost si vous ne souhaitez l’appliquer que sur un site :

<IfModule mod_expires.c>
  <FilesMatch "\.(jpg|gif|png|pdf|css|js)$">
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
  </FilesMatch>
</IfModule>    

Nous avons activé le cache sur les fichiers pour une durée d’un mois, mais n’hésitez pas à le rendre plus court si vous craignez de faire des modifications de temps en temps. Une solution pour autoriser les modifications est d’accoler le timestamp de sa dernière modification au nom du fichier.

Compresser avec mod_deflate

Moddeflate, ou modgzip sur Apache 1.3 compresse les fichiers avant de les envoyer au navigateur pourvu que celui-ci accepte ce mode de transfert. Nous allons l’utiliser pour réduire la taille des fichiers texte envoyés par le serveur : CSS, Javascript, HTML ou XML. Le format texte se compresse en effet très bien, le fichier final faisant jusqu’à 15% de l’original, avec une consommation très faible du processeur.

Comme précédemment, activez le module Apache :

    # a2enmod deflate

Ou si vous utilisez Apache 1.3 :

    # a2enmod gzip
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css text/js application/x-javascript text/plain text/xml
</IfModule>

Désactivez les ETags

Les ETags, pour Entity Tags, sont des informations contenues dans les en-têtes HTTP permettent de savoir si un contenu a été modifié sur le serveur depuis son dernier chargement. Si l’etag sur côté serveur est le même que coté client, alors le serveur renvoie un code de retour 304. Dans le cas contraire, Apache sert le fichier. L’utilisation d’ETag peut s’avérer problématique, notamment dans lorsque la charge est répartie sur plusieurs serveurs. L’ETag est en effet généré à partir d’informations prises sur le système de fichier, et celles-ci changeront d’un serveur à l’autre, rendant l’utilité de l’ETag caduque.

Dans notre configuration actuelle, nous avons tout intérêt à désactiver les etags. En effet, les fichiers sont stockés en cache côté client pendant un mois, ce dernier n’effectuera donc pas la demande de fichier, et pour les autres, on évitera les aller retours à grands coups de 304.

FileETag none

Enfin, redémarrez Apache après en avoir validé la configuration :

    # apache2ctl -t
    # /etc/init.d/apache2 restart

Et voilà, c’est fait. Vous venez d’augmenter très sensiblement les performances de votre application web sans en modifier le code en profondeur. Dans un prochain article, nous verrons comment optimiser encore vos applications en utilisant intelligemment memcached pour stocker le résultat de vos requêtes SQL.

Notre dame vue du pont de la tournelle

Perry the Platypus wants you to subscribe now! Even if you don't visit my site on a regular basis, you can get the latest posts delivered to you for free via Email: