Varnish au service de Catalyst ?

user_icon admin | icon2 Catalyst | icon4 29/12/2008 13h53| Type doc: article| Type File: xml| icon3 No Comment

Varnish au service de Catalyst ?


1. Varnish

Ce paragraphe est largement inspiré des deux articles de ' Catalyst Advent Calendar ' traitant de Varnish :

1.1. Qu'est que Varnish

Vanish est relativement récent, sa première version datant de 2006. Il a été conçu pour résoudre le problème récurrent auquel sont confrontés les développeurs web : Comment améliorer la performance d'un site dont des parties, consommatrice en CPU, sont dynamiques . Il s'agit d'un excellent reverse proxy mis au point par Poul-Henning Kamp. Un gage de qualité lorsque l'on sait qu'il s'agit de l’un des principaux mainteneurs de la couche réseau de FreeBSD. Il assure aussi le load balancing, la réécriture d'url, il est même possible de servir des pages devenues inexistantes sur le serveur Web.

Il y a de nombreux bénéfices à tirés de l'utilisation de Varnish. Tout dabord son language de configuration VCL est extrémement souple, il permet de décrire de manière très avancée le fonctionnement du cache que l'on souhaite. De plus il implémente une partie de la norme ESI ( Edge Side Includes), un petit language basé sur XML pour assembler dynamiquement des contenus Web.

Edge Side Includes est un langage de balise normaisé par le W3C, il nous permet de diviser une page en petit morceaux, d'en cacher chaque élément indépendament et d'en assembler le tout. ESI est complexe, nous ne verrons que les fonctionnalités les plus usuelles :

esi:include permet de charger le contenu d'une autre pièce dans la page courante, c'est la plus couramment utilisée.

esi:remove : Tout ce qui est entre le balises <esi:remove > et </esi:remove > sera supprimé de la page. Pratique pour afficher quelque chose lorsque le mode ESI est désactivé.

<!--esi ... -- > : Lorsque le processeur ESI rencontre ce constructeur, il le supprime mais conserve le contenu.

2. Un simple exemple

Prenons le cas d'une page dont le role est d'afficher la date :

<HTML>
<BODY>
The time is: <esi:include src="/cgi-bin/date.cgi"/>
at this very moment.
</BODY>
</HTML>

Cette page fait appel au cgi /cgi-bin/date.cgi suivant:

#!/bin/sh

echo 'Content-type: text/html'
echo ''
date "+%Y-%m-%d %H:%M"

Le code VCL suivant met en oeuvre le cache de cette page ET du cgi.

sub vcl_fetch {
    if (req.url == "/test.html") {
        esi;  /* Do ESI processing */
        set obj.ttl = 24 h;
    } elseif (req.url == "/cgi-bin/date.cgi") {
        set obj.ttl = 1m;
    }
}

C'est ici qu'entre en jeux Varnish + ESI. ESI au travers du langage VCL de varnish permet de cacher des portions de page avec chacune leur propre règle. Varnish assemble le tout avec les données qu'il a ou non en cache.

Notre site vient de connaitre une réduction drastique dans le traitement nécessaire pour servir chaque page. Cela devient encore plus intéressant lorsque certains bloc sont spécifique à l'utilisateur. Dans le cas classique, sans ESI, il nous aurrait été impossible de cacher ce type de page, avec ESI cela devient trivial :)

On peut imaginer les gains lorsqu'il s'agit de ressources gourmandes telles que requêtes complexes, lecture disque, accès réseaux ...

3. Installation de Varnish

Elle se fait de manière classique, via notre gestionnaire de package préféré. Il est toutefois nécessaire de diposer de la dernière version soit la 2.0.2 qui n'est pas présente par défaut sur Debian Etch. Pour la recréer voir l'article Création d'un dépôt Debian . Les packages de varnish en 2.0.2 pour Debian Etch sont disponibles ICI .

Sous debian le daemon varnishd démarre juste après l'installation avec les paramètres suivants:

/usr/sbin/varnishd -P /var/run/varnishd.pid -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -s file,/var/lib/varnish/htpc/varnish_storage.bin,1G

Le daemon écoute sur le port 6081 ainsi que sur le 6082 pour sa gestion. Son comportement est défini dans le fichier /etc/varnish/default.vcl .

Si l'on se connecte sur http://localhost:6081 , un méchant 'Service Unavailable' nous est retourné. Normal, la config de varnish doit être un minimum adaptée à notre cas.

Dans le fichier de configuration de varnish la première "déclaration" est :

backend default {
.host = "127.0.0.1";
.port = "8080";
}

Voilà pourquoi aucun service n'est disponible, varnish cherche a cacher les pages de http://localhost:8080/ alors que nous n'avons rien à l'écioute sur ce port. Qu'à cela ne tienne ...

catalyst.pl MonApp
cd MonApp
./script/monapp_server.pl -p 8080

Connexion à nouveau sur http://localhost:6081, et là oh merveille nous avons la page de l'application MonApp :)

Un petit test de performance s'impose, pour cela je lance un Apache Benchmark (ab) sur l'application elle même est ensuite à travers le cache:

ab -c 10 -n 500 http://localhost:8080/
...
HTML transferred:       2825000 bytes
Requests per second:    233.26 [#/sec] (mean)
...
ab -c 10 -n 500 http://localhost:6081/
...
HTML transferred:       2867085 bytes
Requests per second:    5383.23 [#/sec] (mean)
...

Gloup ... un rapport de 23 :)

Bon ok l'application n'a pas de cache, je reteste sur une vraie application (catapulse) toujours en local avec cette fois-ci avec un cache:

ab -c 10 -n 500 http://localhost.catapulse.org/
...
HTML transferred:       5841500 bytes
Requests per second:    113.86 [#/sec] (mean)
...
ab -c 10 -n 500 http://localhost.catapulse.org:6081/
HTML transferred:       5876549 bytes
Requests per second:    5130.05 [#/sec] (mean)

Arghhh ... un rapport de 45 cette fois-ci !!!

Ebourrifant non ? En tant que Proxy il accompli parfaitement son travail, maintenant pour ce qui est d'ESI je suis un peu plus sceptique. En effet cette approche casse la logique MVC de Catalyst car les vues appellent des controleurs, l'affichage controle le flux ... pas bien.

L'idéal serait la mise en oeuvre d'un cache gérant la dépendance des portions de page. En clair, une action modifie le contenu d'une portion de page, par exemple l'ajout d'un commentaire, cette dernière 'sait' qu'elle doit supprimer le cache de la page complète pour un recalcul. En rendant récursif ce principe il devient possible de ne recalculer que ce qui est vraiment nécessaire.

-------------------------------------------------
|            PAGE                |   SIDEBAR    |
|                                |--------------|
|                                |   CATEGORIES |
|           CONTENT              |   COMMENTAIRES
|            ...                 |   ...        |

Dans cet exemple nous avons 5 objets à cacher. L'arbre des dépendances pourrait être celui-ci:

PAGE--|--CONTENT
      |--SIDEBAR--|--CATEGORIES
                  |--COMMENTAIRES

Lors du appel à cette page, tous les objets sont calculés et mis en cache. Au second passage, PAGE est en cache donc retournée immédiatement. Un utilisateur fait alors un commentaire sur le contenu de la page. Gràce à l'arbre des dépendances l'objet COMMENTAIRES détruit le cache de SIDEBAR et de PAGE et met en cache COMMENTAIRES. Lors du prochain passage PAGE n'est plus en cache, on recalcule alors recurivement ce qui est nécessaire : SIDEBAR et PAGE

Une future version de Catapulse ?


Add_a_comment

Validator_logo
Catapulse v0.06
( 0.081031 s)