Varnish devant WordPress sur Apache

Varnish-Cache

Alors je ne sais pas si vous avez remarqué, mais le blog va (un peu) plus vite à charger ces derniers temps ? Après mon serveur n’est pas monstrueux non plus (1 cœur/2GB RAM : ne vous amusez pas à me faire un DDOS, ça tombera probablement dès la 10ème connexion simultané…)

Bref, j’ai suivi une partie de cet article pour essayer d’améliorer, modestement les performances du blog, j’ai déjà :

  • Mis facilement WP Super Cache en place, et fait les réglages associés ;
  • Ajouté le Plugin WP Smush pour compresser les images sans pertes (toujours ça de gagné) ;
  • Utilisé gtmetrix.com et webpagetest.org pour savoir quoi améliorer sur le site ; et
  • J’ai fait un peu de ménage dans les « grosses » images qui étaient sur la page d’accueil, pour éviter qu’elles ne soient re-sizées par votre navigateur, et vous servir de suite celle à la bonne taille.

Bon après j’ai sauté la partie gestion des commentaires (il n’y en a presque pas pour l’instant), et je n’ai pas encore abordé la partie base SQL. Du coup il me reste le caching avec un reverse-proxy pour continuer d’optimiser.

Optimiser pour quoi faire ?

Alors c’est très simple : depuis quelque temps maintenant Google s’est mis à prendre en compte le temps de chargement des pages comme critère de référencement. Pour faire simple, il ne suffit plus :

  • d’être cohérent dans le contenu de votre site par rapport à la recherche de l’utilisateur ; ni
  • d’être « référencé » par plein de site, ou encore
  • d’avoir plein de clic sur son site dans les recherches.

Il faut, en plus, être capable de répondre rapidement aux demandes pour monter dans les classements ! Du coup tout le monde s’y met…

Varnish ?

Principe Proxy
Principe Proxy « classique »

Varnish c’est un serveur de cache, ça veut dire qu’il fait un peu la même chose que WP Super Cache sauf qu’il le fait de manière externe à WordPress. Avec WP Super Cache quand un client charge une page une première fois, tous les clients suivant rechargeront bien la même page car elle aura été mise en cache. Néanmoins, à chaque connexion d’un client Apache construira quand même un processus pour servir le client ; et ça : ça reste coûteux et temps et ressources pour le serveur : capiche ?

C’est là que Varnish intervient, lui il se charge de faire le bureau d’accueil de votre site et servir encore et toujours les même pages à vos clients, sans demander au serveur apache derrière lui, tant qu’il sait quoi retourner.

Par rapport au schéma à côté, il faut imaginer que le proxy ne demande l’heure au poste B, qu’une fois par minute (puisqu’il retourne l’heure avec sans les secondes). Exemple : si un poste C demandai l’heure à B juste après A, le proxy se contentera de renvoyer la même réponse : sans trop réfléchir, ni demander à B. Et là, il change d’apache : c’est que comme il sert les pages les plus utilisées il le fait beaucoup plus rapidement qu’un Apache bien gras.

Si on fait la comparaison avec une préfecture : Varnish c’est la gentille hôtesse d’accueil qui donne toute la journée les 3 mêmes papiers ; Apache c’est le cadre bac+42 dans le bureau derrière qui va retrouver le laissez-passer A-38, mais pour lequel il doit d’abord obtenir le formulaire A-39 selon la circulaire B-65… avant de vous le rendre 2h plus tard, et surtout de refaire la même chose quand la même demande arrivera plus tard…

Nginx est utilisé par beaucoup de site pour faire ce boulot-là, même si à la base c’est un serveur web (et aussi un serveur de cache) bien plus « vif » qu’apache (le pourquoi est très bien expliqué ).

Moi j’aime bien Apache et Nginx c’est russe, en plus, ça me fait 2 raison d’utiliser à Varnish plutôt que Nginx.

Installation

Bon alors l’installation est super bien packagée pour une fois : toutes les (5) instructions OS par OS sont disponibles ici. Et plus particulièrement pour ma Debian 7 avec la version 4.0 de Varnish ça donne ça :

apt-get install apt-transport-https
curl https://repo.varnish-cache.org/GPG-key.txt | apt-key add -
echo "deb https://repo.varnish-cache.org/debian/ wheezy varnish-4.0" >> /etc/apt/sources.list.d/varnish-cache.list
apt-get update
apt-get install varnish

Configuration test d’un site sous apache avec Varnish

Avant lancer Varnish en écoute sur le port 80 : on va l’essayer sur un autre port, vérifier que tout fonctionne bien (sans toucher à l’accès standard http sur apache pour l’instant), puis on échangera les ports pour mettre Varnish « en frontal » quand on aura validé que tout marche bien comme on veut.

La configuration de Varnish se trouve dans les fichiers suivant :

  • /etc/varnish/default.vcl
  • /etc/default/varnish

De la théorie :

Par contre pour la configuration du fichier VCL (Varnish Configuration Language), ça se complique carrément beaucoup. Je vais être clair ça manque d’exemples « complets » sur le ‘net (et d’exemple de mec qui ont compris ce qu’ils font), et la doc officielle est pas vraiment digeste quand on commence…

J’en veux pour preuve ces 2 schémas « récapitulatif » du traitement, disponibles sur le site officiel, je vous redonne le premier ici :

Varnish cache fct
Schéma du traitement d’une requête pas Varnish « côté client »

C’est d’autant moins intuitif qu’on ne fait que définir dans le fichier VCL des traitements supplémentaires à l’algorithme ci-dessus, c’est-à-dire en supplément de ce que fera Varnish de toute façon.

Bon en mélangeant un peu tout ça à la documentation texte ici, et ailleurs, et on finit par comprendre 2-3 trucs (et choper une bonne migraine aussi). J’ai essayé de vous résumer ce que je comprends l’algo ici :

Lorsqu’un client envoie une requête à Varnish :

  1. La routine vcl_recv est appelée en premier : son but est de décider s’il faut « servir » la demande, ou la refuser,
    et faire éventuellement un peu de ménage dans la requête (cookies).
    Elle peut terminer par un appel à l’une de ces 5 autres routines :

    1. pass : la requête sera traitée mais le résultat ne sera pas « caché » par Varnish (pour les pages d’admin du site par exemple) ;
    2. pipe : une fois appelé, la requête sera traitée sans action de Varnish, il se contentera juste de transférer la communication ;
    3. synth : renvoi un objet construit par Varnish (mais hors cache), typiquement pour retourner « coucou-test » ou quelques cas d’erreur ;
    4. purge : demande à Varnish de vider le cache (sur demande, par exemple à la publication d’un nouvel article) ;
    5. hash : C’est ce qui va nous intéresser, en fait pour indexer les pages dans le cache Varnish utilise un « hash » de la requête, à partir de ce hash on va pouvoir faire un « lookup », c’est-à-dire chercher la page dans le cache pour la servir.
  2. lookup : Cette partie n’apparaît pas dans le fichier VCL : Varnish fait son boulot de recherche dans son cache et passe ensuite la main à une des trois sous routines suivante :
    1. pass (comme au-dessus), dans le cas où la recherche dans la cache à retourner un « hit_for_pass »
      Un « hit_for_pass » (qui est très bien expliqué ) : C’est un cas identique au « miss » ci-dessous (on ne trouve pas la page dans le cache), mais une requête précédente a marqué la page comme « ne pouvant pas être mise en cache », indiquant ainsi à Varnish de passer en mode pass sur ces requêtes systématiquement.

      1. De là, on passe la demande au serveur (backend) pour récupérer la page.
      2. et on la passe à deliver
    2. miss : la page n’a pas été trouvé dans le cache ;
      1. on passe donc la demande au serveur (backend) pour récupérer la page.
      2. et on la passe à deliver
    3. hit : la page est présente dans le cache
      1. on charge la page depuis le cache (avec vérification d’expiration du cache, si c’est le cas on lance un rechargement la page dans le cache en arrière-plan)
      2. et on la passe à deliver
  3. Deliver : C’est la dernière fonction dans Varnish avant de renvoyer le contenu au client.
    1. Typiquement on va y indiquer si la page provient du cache ou non, masquer la version de PHP d’Apache, etc.

Et c’est tout pour la partie Front End. Je fais le choix ne pas vous parler trop de la partie Back End. En fait ça marche comme on pourrait s’y attendre pour un mécanisme de cache. La seule fonction qui va vraiment nous intéresser là-dedans, c’est vcl_backend_response qui permet de modifier la réponse renvoyée par le serveur « backend », qu’on verra un peu plus bas.

A la pratique…

Bon dans les faits, le premier truc à regarder c’est le fichier /etc/default/varnish pour contrôler sur quel port Varnish écoute. Pour ma config de test, j’ai laissé le choix deux proposé par la config par défaut :

## Alternative 2, Configuration with VCL
#
# Listen on port 6081, administration on localhost:6082, and forward to
# one content server selected by the vcl file, based on the request.
# Use a 256MB memory based cache.
# firewall if
DAEMON_OPTS="-a :6081 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

Ça c’était facile, j’ai rien modifié…^^

Le fichier VCL

Et le vif du sujet notre fichier en Varnish Configuration Language. Première action : définir la version du langage, j’ai installé un Varnish 4 donc :

vcl 4.0;

Définir nos Backends

Ensuite on va définir nos « backends », pour Varnish : c’est le serveur de contenu qu’il doit cacher. Dans mon cas j’en ai 2, ce blog, et un autre blog photo avec ma chérie.
Pour moi Apache fait déjà le boulot de diriger les requêtes vers l’un ou vers l’autre en fonction de l’URL demandé, donc je peux faire ça :

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "127.0.0.1";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

backend photo {
    .host = "127.0.0.1";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 1s;
        .interval = 5s;
        .window = 5;
        .threshold = 3;
    }
}

Mais on pourrait aussi proposer le second site sur un autre port et éviter à Apache de faire ce travail (SPOILER-ALERT : ce qu’on fera dans la config finale à la fin)

Une ACL

Ensuite une micro étape où on définit une ACL (par IP) local dont on se servira juste après :

acl purge {
    "localhost";
    "127.0.0.1";
}

La requête HTTP : donnée de travail

Avant de regarder la suite, il faut comprendre à quoi ressemble une requête en HTTP (pas HTML, hein). C’est HTTP qui est utilisé quand vous faite un GET ou un POST, typiquement si on regarde dans un Whireshark quand je connecte à ce site :

Requête HTTP - GET
Requête HTTP – GET

C’est principalement (mais pas que) sur cette partie de la communication entre le client et le serveur que Varnish va agir.

vcl_recv

Après, comme j’ai expliqué à la réception d’une requête la première fonction appelé c’est vcl_recv (pour « receive ») à la réception d’une requête, et c’est donc sur cette requête HTTP qu’on va agir dans le VCL.

# This function is used when a request is send by a HTTP client (Browser)
sub vcl_recv {

Première étape, on va supprimer le port TCP du champ host (si présent), dans mon cas ça va permettre d’utiliser le même cache si mon site est accessible depuis un port ou un autre (genre le 80, et le 6081 pour les tests)

# Normalize the header, remove the port (in case you're testing this on various TCP ports)
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");

Ensuite, diriger vers le bon « backend » en fonction du champ host dans la recherche.

if (req.http.host ~ "geekeries.org") {
    set req.backend_hint = default;
} elsif (req.http.host ~ "etienneetlaure.fr") {
    set req.backend_hint = photo;
}

Ensuite, on va faire plein de traitement pour optimiser et sécuriser le mécanisme de cache. Déjà, on va autoriser uniquement local host à demander des requêtes PURGE, à l’aide de l’ACL définie juste AVANT :

# Allow purging from ACL
if (req.method == "PURGE") {
    # If not allowed then a error 405 is returned
    if (!client.ip ~ purge) {
        return(synth(405, "This IP is not allowed to send PURGE requests."));
    }
    # If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
    return (purge);
}

Puis s’assurer qu’on ne cachera pas les pages incluant des requêtes de type POST (parce que ce serait mal) :

# Post requests will not be cached
if (req.http.Authorization || req.method == "POST") {
     return (pass);
}

On arrive à un bloc d’optimisation spécifique à WordPress (là, j’admets j’ai beaucoup repris des choses trouvé çà et là sur le net), mais rien de bien compliqué donc je vous le laisse donc tel quel :

# --- WordPress specific configuration
# Did not cache the admin and login pages
if (req.url ~ "wp-(login|admin)" || req.url ~ "preview=true") {
    return (pass);
}

# Did not cache the RSS feed
if (req.url ~ "/feed") {
    return (pass);
}

# Remove has_js and CloudFlare/Google Analytics __* cookies.
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");

# Remove a ";" prefix, if present.
set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

# Remove the "has_js" cookie
set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

# Remove any Google Analytics based cookies
set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");

# Remove the Quant Capital cookies (added by some plugin, all __qca)
set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");

# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");

# Are there cookies left with only spaces or that are empty?
if (req.http.cookie ~ "^ *$") {
    unset req.http.cookie;
}

# Cache the following files extensions
if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
    unset req.http.cookie;
}

# Normalize Accept-Encoding header and compression
# https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
if (req.http.Accept-Encoding) {
    # Do no compress compressed files...
    if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
        unset req.http.Accept-Encoding;
    } elsif (req.http.Accept-Encoding ~ "gzip") {
        set req.http.Accept-Encoding = "gzip";
    } elsif (req.http.Accept-Encoding ~ "deflate") {
        set req.http.Accept-Encoding = "deflate";
    } else {
        unset req.http.Accept-Encoding;
    }
}

# Check the cookies for wordpress-specific items
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
    return (pass);
}
if (!req.http.cookie) {
    unset req.http.cookie;
}
# --- End of WordPress specific configuration

Vous noterez que depuis le départ, on ne fait que des « return (pass) » ou retirer des éléments de notre requête. Du coup arrivé ici, la requête est « propre » : on peut la passer à hash (expliquée dans la partie algo plus haut).

# Cache all others requests
return (hash);

Et c’est tout pour vcl_recv()

pipe et pass

Du coup, on va définir pipe et pass (qui ne font rien en particulier chez moi, on pourrait ne pas le mettre) :

sub vcl_pipe {
        return (pipe);
}
sub vcl_pass {
        return (fetch);
}

vcl_hash

Et la plus importante : hash, dans laquelle on va construire l’élément (le condensat ou hash issu de notre requête) sur lequel Varnish va indexer la page demandée dans le cache. Ici c’est le comportement par défaut (très bien expliqué ici), à chaque appel on va construire un hash à partir de l’URL demandée et, selon la disponibilité, du host HTTP ou de l’adresse IP du serveur interrogé :

# The data on which the hashing will take place
sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }
    # If the client supports compression, keep that in a different cache
    if (req.http.Accept-Encoding) {
        hash_data(req.http.Accept-Encoding);
    }
    return (lookup);
}

vcl_backend_response

Et comme je l’avais expliqué plus haut, hash passe à lookup pour rechercher un élément correspondant à notre condensat dans le cache, ou demander au backend de servir la page si elle n’y est pas présente. Dans le cas où on descend jusqu’au Back End, on va passer dans vcl_backend_response avant de renvoyer à réponse à deliver.

Je n’ai pas trop parlé de la partie Backend de Varnish avant, en fait :  vcl_backend_response permet d’agir sur la réponse du serveur (et son header HTTP donc) avant que celle-ci ne soit mise en cache par Varnish. Typiquement on va y refaire des traitements comme pour recv() mais indiquant cette fois de ne pas cacher la page. Je vous la donne en un bloc :

# This function is used when a request is sent by our backend (Nginx server)
sub vcl_backend_response {
        # Remove some headers we never want to see
        unset beresp.http.Server;
        unset beresp.http.X-Powered-By;

        # For static content strip all backend cookies
        if (bereq.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
                unset beresp.http.cookie;
        }
        # Don't store backend
        if (bereq.url ~ "wp-(login|admin)" || bereq.url ~ "preview=true") {
                set beresp.uncacheable = true;
                set beresp.ttl = 30s;
                return (deliver);
        }

        # Only allow cookies to be set if we're in admin area
                if (!(bereq.url ~ "(wp-login|wp-admin|preview=true)")) {
                unset beresp.http.set-cookie;
        }

        # don't cache response to posted requests or those with basic auth
        if ( bereq.method == "POST" || bereq.http.Authorization ) {
                set beresp.uncacheable = true;
                set beresp.ttl = 120s;
                return (deliver);
        }

        # don't cache search results
        if ( bereq.url ~ "\?s=" ){
                set beresp.uncacheable = true;
                set beresp.ttl = 120s;
                return (deliver);
        }

        # only cache status ok
        if ( beresp.status != 200 ) {
                set beresp.uncacheable = true;
                set beresp.ttl = 120s;
                return (deliver);
        }

        # A TTL of 2h
        set beresp.ttl = 2h;
        # Define the default grace period to serve cached content
        set beresp.grace = 30s;

        return (deliver);
}

vcl_deliver

On arrive au bout, notre réponse va être renvoyée au client, mais on veut encore faire quelques traitements sur celle-ci, par exemple de sécurité pour éviter de pousser tous les numéros de versions des technos utilisées par le site :

sub vcl_deliver {
        if (obj.hits > 0) {
                set resp.http.X-Cache = "cached";
        } else {
                set resp.http.x-Cache = "uncached";
        }

        # Remove some headers: PHP version
        unset resp.http.X-Powered-By;

        # Remove some headers: Apache version & OS
        unset resp.http.Server;

        # Remove some heanders: Varnish
        unset resp.http.Via;
        unset resp.http.X-Varnish;

        return (deliver);
}

init et fini

Et c’est tout ! On va juste rajouter les fonctions init et fini s’exécutant 1 fois au chargement et déchargement du fichier VCL respectivement (pour charger des modules typiquement, mais pas utilisée dans mon cas)

sub vcl_init {
        return (ok);
}
sub vcl_fini {
        return (ok);
}

Voilà, il ne vous reste plus qu’à comprendre, concaténer et adapter les lignes de code ci-dessus et vous devriez obtenir deux fichiers de configuration pour Varnish 4 tout beau pour un WordPress basique.

Mise en route

Pour démarrer Varnish et lui faire charger ses 2 fichiers de conf, un simple :

root@server:~# service varnish restart
[ ok ] Stopping HTTP accelerator: varnishd.
[ ok ] Starting HTTP accelerator: varnishd.

fera le boulot.

Tests !

Bon et c’est bien tout ça, mais ça marche en vrai ? Pour savoir, on va commencer par utiliser « ab » (pour apache-bench) pour tester un serveur http. Du coup je vous rappelle la configuration à ce moment :

J’ai toujours mon site sous apache directement en frontal sur le port 80, et sur le port 6081 j’ai le même site mais avec Varnish devant pour réaliser le cache-proxy.

Test du site sans Varnish

Soit la commande suivante pour établir 100 connexions via 5 threads parallèles sur le site :

root@server:~# ab -n 100 -c 5 http://geekeries.org/

Et le résultat :

Server Software:        Apache/2.x.xx
Server Hostname:        geekeries.org
Server Port:            80

Document Path:          /
Document Length:        39874 bytes

Concurrency Level:      5
Time taken for tests:   0.245 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      4026100 bytes
HTML transferred:       3987400 bytes
Requests per second:    407.79 [#/sec] (mean)
Time per request:       12.261 [ms] (mean)
Time per request:       2.452 [ms] (mean, across all concurrent requests)
Transfer rate:          16033.32 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   1    1.4      1       8
Processing:     4   11   4.9     11      29
Waiting:        0    9   4.8      8      28
Total:          5   12   4.7     11      29

Percentage of the requests served within a certain time (ms)
  50%     11
  66%     13
  75%     14
  80%     15
  90%     17
  95%     19
  98%     29
  99%     29
 100%     29 (longest request)

Test du site avec Varnish

Et la même commande sur le port 6081 :

root@smtp:~# ab -n 100 -c 5 http://geekeries.org:6081/

Et le résultat :

Benchmarking geekeries.org (be patient).....done

Server Software:
Server Hostname:        geekeries.org
Server Port:            6081

Document Path:          /
Document Length:        39853 bytes

Concurrency Level:      5
Time taken for tests:   0.119 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      4017402 bytes
HTML transferred:       3985300 bytes
Requests per second:    838.25 [#/sec] (mean)
Time per request:       5.965 [ms] (mean)
Time per request:       1.193 [ms] (mean, across all concurrent requests)
Transfer rate:          32886.64 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.7      1       3
Processing:     1    4   1.6      4      13
Waiting:        0    2   1.6      2       9
Total:          4    6   1.7      5      15

Percentage of the requests served within a certain time (ms)
  50%      5
  66%      5
  75%      6
  80%      6
  90%      7
  95%     10
  98%     12
  99%     15
 100%     15 (longest request)

Bénéfice direct

Si on compare on se rend compte des différences suivantes :

  • Server Software n’apparaît plus dans la version avec Varnish (comme demandé dans vcl_deliver) ;
  • les tailles de documents récupérés sont similaires (mais change un peu, on a supprimé quelques trucs avec Varnish) ;
  • Surtout, on a mis un 0.245s à effectuer les tests sans Varnish et uniquement 0.119s avec Varnish soit de 48% plus vite.

Ensuite toutes les stats redisent à peu près la même chose, 2 fois moins de temps en moyenne pour répondre aux requêtes. Et ça c’est cool, ça nous dit déjà que le site pourrait probablement doubler son activité avec Varnish, tout en utilisant les mêmes ressources qu’Apache actuellement.

Bénéfice dans la vraie vie:

J’ai refait des tests ensuite grandeur nature avec GTMetrix et Webpagetest, ça m’a fait gagner plus d’une seconde au chargement complet de la page, et un bon gain de 100ms au niveau du TTFB (Time to First Byte), et une page qui commence à s’afficher dans le navigateur beaucoup plus vite aussi.

En graphique, le comparatif pour l’affichage dans le navigateur (bien représentatif du ressenti utilisateur) :

Affichage avec et sans Varnish
Affichage effectif dans le navigateur avec ou sans Varnish

En graphique, le comparatif des différentes valeurs de timings (notamment utile pour les moteurs de recherches) :

Timings avec ou sans Varnish
Différents Timings avec ou sans Varnish

Et là on se rend vraiment compte de l’intérêt du bestiau. Ce n’est pas rien quand on sait que le serveur n’est qu’un misérable monocœur avec 2Go de RAM qui n’a jamais été pensé pour héberger deux WordPress gourmand.

Mise en frontal de Varnish

Sans hésitation désormais, pour mettre Varnish en Frontal devant Apache, il faut faire un peu de tricot :

  1. Déplacer les sites HTTP vers un autre port (8080 et 8081 par exemple) ;
  2. configurer Varnish pour que les « backend » dans le fichier VCL pointent vers ces sites ;
  3. configurer Varnish pour écouter sur le port 80 à la place ;
  4. redémarrer les services.

Dans la console ça donne :

vim /etc/apache2/sites-available/wordpress
    <VirtualHost *:8080>

vim /etc/apache2/sites-available/wordpressphoto
    <VirtualHost *:8081>

vim /etc/apache2/ports.conf
    NameVirtualHost *:8080
    NameVirtualHost *:8081
    Listen 8080
    Listen 8081

Ensuite on fait re-pointer Varnish vers les bons ports :

vim /etc/varnish/default.vcl
backend default {
    .host = "127.0.0.1";
    .port = "8080";
}

backend photo {
    .host = "127.0.0.1";
    .port = "8081";
}

Puis Varnish en écoute sur le port 80 (et on en profite pour passer le cache à 1 GB aussi) :

vim /etc/default/varnish
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,1G"

Et on termine en redémarrant Apache puis Varnish

service apache2 restart
service varnish restart

Il suffit ensuite de vérifier que le site fonctionne bien :

wget http://geekeries.org/
[...]
HTTP request sent, awaiting response... 200 OK

Ok tout va bien, on est arrivé au bout !

Purge et WordPress

Pour terminer, je vous recommande d’installer l’extension Varnish HTTP Purge dans vos WordPress pour éviter d’avoir à vous taper les requêtes PURGE à la main à chaque fois que vous publierez un article ou modifier un paramètre du CSS du blog. Sinon si, vous êtes un barbu avec des poils et tout :

curl -X PURGE <site.tld>

Conclusion

Bon j’espère que ça vous aura intéressé, ça m’a pris un peu de temps pour détricoter tout le fonctionnement de Varnish en tout cas… En pratique, ça montre des vrais résultats (même sur mon serveur préhistorique). Je serai curieux de voir ce que ça peut donner sur un site avec un « gros » serveur derrière. Il vous reste quelques trucs à étudier quand même : notamment l’intérêt de mettre en place le cache sur https (ce que je n’ai pas fait), ou encore calculer la taille idéale du log, et savoir lire les logs de Varnish (en RAM) avec les outils d’administration.

Byz à tous et à vous de jouer.

PS: un petit merci à ce blog pour la mise en route de cette article sur Varnish

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. Apprenez comment les données de vos commentaires sont utilisées.