Subtilités du cache FastCGI Nginx avec WordPress

Source : nginx.org

Source : nginx.org

J’ai récemment écrit un article récapitulant les différents niveaux de cache offerts par Nginx, et je vous avais notamment parlé du très efficace cache FastCGI. Il s’avère que si vous souhaitez faire fonctionner celui-ci avec PHP-FPM et votre WordPress, il va falloir mettre un peu les mains dans le cambouis…

Petits rappels pour ceux qui n’auraient pas lu le précédent article : WordPress est écrit en PHP. Le PHP génère du HTML. Le cache FastCGI se charge de mettre ce code HTML en cache.

Ok cool, il est où le problème ?

Le problème, c’est que lorsque vous allez ajouter un nouvel article par exemple, celui-ci n’apparaîtra pas lors de sa publication, puisque Nginx continuera de délivrer le contenu qu’il a en cache ! Il nous faut aussi filtrer certains types de requêtes : par exemple si on envoie une requête HTTP de type POST, cette requête ne doit pas être adressée au cache, mais bien au script PHP chargé de la traiter…

Et on ne peut pas purger le cache au moment où on publie notre article ?

Si, si vous avez souscrit à la version payante de Nginx… Pour les autres, que neni. Heureusement il existe des modules tiers qui permettent de purger le cache FastCGI de Nginx de manière très précise. Ben oui on ne va pas s’amuser à supprimer tout le cache à chaque publication ça n’aurait pas trop de sens. Le seul hic, c’est que contrairement à Apache, Nginx ne supporte pas le chargement de module à la volée. Il faut recompiler Nginx à la main en incluant les modules désirés.

Pré-requis : le module ngx_cache_purge

Pour garder les choses claires, je vous propose un article dédié à la compilation manuelle de Nginx, avec l’ajout de modules personnalisés. Dans notre cas il faudra ajouter le module ngx_cache_purge, développé par FRiCKLE, et que vous trouverez sur GitHub.

Pour les plus intrépides d’entre vous, sachez que rtcamp propose une version de Nginx modifiée, incluant ce fameux module, mais il va falloir d’abord ajouter leurs dépôts, désinstaller votre Nginx actuel si vous l’avez déjà installé, et réinstaller la nouvelle version :

sudo add-apt-repository ppa:rtcamp/nginx
sudo apt-get update
sudo apt-get remove nginx*
sudo apt-get install nginx-custom
Ce n’est clairement pas la méthode que j’ai utilisée ici…

Deuxième pré-requis : le module WordPress Nginx Helper

C’est ce module WordPress qui va être chargé de demander à Nginx de supprimer certaines parties du cache FastCGI lors de l’ajout de contenu. Je ne vous apprends pas comment installer un module WordPress, le web en parle déjà assez. La configuration ressemble à ceci chez moi :

Cliquer pour agrandir

Cliquer pour agrandir

À vous de voir après comment vous souhaitez modifier la configuration… Dans tous les cas, si tout comme moi vous placez votre cache dans un dossier autre que /var/run/nginx-cache (qui est la configuration par défaut), il va falloir l’indiquer au module en ajoutant au fichier wp-config.php le paramètre :

define('RT_WP_NGINX_HELPER_CACHE_PATH','/chemin/du/cache-nginx/');

Configuration de Nginx

Il va falloir mettre à jour notre server-block Nginx pour que le dialogue puisse être établi avec WordPress. Ajoutez les 4 lignes suivantes dans le fichier /etc/nginx/nginx.conf :

http {
[...]
  fastcgi_cache_path      /var/cache/nginx levels=1:2 keys_zone=nginxcache:10m inactive=1h max_size=500m;
  fastcgi_cache_key       "$scheme$request_method$host$request_uri";
  fastcgi_cache_use_stale error timeout invalid_header http_500;
  fastcgi_ignore_headers  Cache-Control Expires Set-Cookie;
[...]
}

Adaptez les valeurs à vos besoins…

Je vous avais déjà parlé de certains de ces paramètres dans mon précédent article, si vous avez des doutes, la documentation officielle est par ici, sinon il y a les commentaires.

Il va ensuite falloir adapter le server-block de votre site WordPress. Le mien se situe dans /etc/nginx/sites-available/www.guillaume-leduc.fr.conf, voici ce que j’ai ajouté :

server {
    [...]
    set $skip_cache 0;
 
    # Les requêtes POST ne vont pas en cache
    if ($query_string != "") { set $skip_cache 1; }
 
    # L'administration ne va pas en cache
    if ($request_uri ~* "/wp-admin/|xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") { set $skip_cache 1; }
 
    # Les utilisateurs identifiés non plus
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; }
 
    # On applique le cache 
    location ~* \.php$ {
        try_files $uri =404;
        fastcgi_pass php5-fpm-sock;
        fastcgi_index index.php;
        include fastcgi.conf;
 
        # Cache FastCGI
        fastcgi_cache nginxcache;
        fastcgi_cache_valid 60m;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
    }
 
    # L'URI /purge/ permettra de purger certaines entrées du cache
    location ~ /purge(/.*) {
        fastcgi_cache_purge nginxcache "$scheme$request_method$host$1";
    }

À noter qu’il peut être intéressant de combiner ce cache au cache navigateur dont j’ai déjà parlé précédemment. Après avoir testé votre configuration, vous pouvez redémarrer Nginx !

sudo nginx -t
sudo service nginx restart

BONUS : placer le cache en RAM

Je vous le disais, vous avez la possibilité de placer ce cache FastCGI en mémoire vive si vous en avez suffisamment, afin de permettre à Nginx de délivrer votre contenu encore plus rapidement. Si on jette un œil à nos points de montage :

df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sda1           20G    5,4G   14G  29% /
udev                10M       0   10M   0% /dev
tmpfs              200M    340K  200M   1% /run
tmpfs              5,0M       0  5,0M   0% /run/lock
tmpfs              502M       0  502M   0% /dev/shm
/dev/sda2          439G    103G  314G  25% /home

On s’aperçoit de la présence d’un type de système de fichier un peu spécial intitulé tmpfs. TMPFS est un outil vraiment intéressant qui permet au système d’accéder à des emplacements mémoire de la RAM (s’il y en a de disponible) pour y stocker du contenu. C’est le remplaçant du RAMdisk, et c’est tout simplement un petit espace sur votre RAM qui est donc idéal pour stocker des données temporaires comme… du cache.

Si j’avais voulu placer le cache fastCGI dans cet espace, il aurait simplement fallu que je créé un dossier /dev/shm/nginx-cache et que je modifie ma configuration en conséquence. Généralement l’espace tmpfs fait 20% de votre RAM totale. Étant à 2Go sur mon petit Kimsufi, on est bien à 500Mo pour /dev/shm.

BONUS : tester le fonctionnement du cache FastCGI Nginx

Comment savoir si mon cache fonctionne ? On peut très bien surveillez la taille du dossier de cache, charger des pages du site et vérifier si le cache grossi… Mais comment s’assurer que Nginx UTILISE le cache pour répondre aux requêtes ?

Il suffit d’utiliser la variable Nginx upstream_cache_status, qui ajoutera aux entêtes de réponse HTTP de précieuses informations.

Ne laissez pas ce genre d’information en production, n’utilisez ceci qu’en développement.

Ajoutez la ligne suivante dans le server-block, ou dans l’uri que vous souhaitez tester :

server {
    [...]
    add_header Fastcgi-Cache $upstream_cache_status;
    [...]
}

Rechargez Nginx.

sudo service nginx reload

Et accédez à la page que vous souhaitez tester, l’entête de la réponse devrait ressembler à ceci :

Cliquer pour agrandir

Cliquer pour agrandir

Trois valeurs possibles :

  • HIT : signifie que le contenu que vous voyez est issu du cache FastCGI
  • MISS : signifie que le contenu n’est pas encore en cache. Rechargez la page et vous devriez avoir un HIT
  • BYPASS : signifie que Nginx a rencontré une condition qui désactive le cache

Si tout se passe bien, pensez à retirer la valeur et recharger Nginx !

Source : rtcamp.com

Cet article vous a plu ? Partagez-le sur les réseaux sociaux !

Twitter Facebook Google Plus email