Servir rapidement ses images avec nginx et dragonfly

Publié le 27 février 2015 par Martin Catty | système

Cet article est publié sous licence CC BY-NC-SA

Lorsqu’on utilise la gem dragonfly, le chargement des images de notre application ressemble à cela :

I, [2015-02-27T16:16:32.957778 #3191]  INFO -- : DRAGONFLY: GET /media/W1siZiIsIjIwMTUvMDIvMjEvOWoxOXhscmMzMV9NX2VuZmxhbW1lX2xlc19jZXNhcl8yMDE1XzAuanBnIl0sWyJwIiwidGh1bWIiLCI3OTJ4NDAwIyJdXQ/-M--Ceremonie%20des%20Cesar%2C%20M%20fait%20son%20cinema-actu_0?sha=ca1afcbcf31555c8 200

On ne peut donc pas demander à nginx de servir directement le fichier depuis le système de fichier car son URL ne correspond pas à son chemin sur le serveur.

C’est problématique car on va demander à notre serveur ruby de servir ces images à chaque fois, ce qui va s’avérer peu performant.

Mise en place d’un proxy cache

Nginx nous offre une directive proxy_cache_path pour faire en sorte de mettre en cache le résultat de certaines URL.

Tout d’abord nous allons créer notre répertoire de cache :

mkdir -p /etc/nginx/cache/dragonfly
chown -R nobody:root /etc/nginx/cache/dragonfly

puis référencer notre cache dans notre fichier nginx.conf.

http {
  proxy_cache_path /etc/nginx/cache/dragonfly levels=2:2 keys_zone=dragonfly:100m inactive=30d max_size=1g;
}

La directive levels définit la profondeur des dossiers créés, ex: /etc/nginx/cache/dragonfly/aa/11.

En 1:1 on aurait quelquechose comme /etc/nginx/cache/dragonfly/a/1.

Cette arboresence est systématiquement reprise dans les fichiers stockés dans ces dossiers de sorte qu’ils puissent retrouver simplement leur place en cas de déplacement, ex: /etc/nginx/cache/dragonfly/ff/84/718ba36b52491e18c227650da4e884ff

La directive keys_zone définit le nom de notre cache et la taille pour les clés. Il s’agit bien des clés de cache et pas des fichiers mis en cache. Une zone de 1M permet de stocker 8 000 clés.

inactive permet de retirer du cache un fichier non accédé depuis un certain temps. Par défaut c’est 10 minutes, ici on utilise 30 jours.

Enfin max_size définit la taille cumulée des fichiers mis en cache. Quand cette taille est atteinte nginx retire les entrées qui ont été utilisées il y a le plus longtemps.

Si un fichier a été mis en cache il y 20 jours et accédé aujourd’hui il sera prioritaire par rapport à un fichier mis en cache il y a 2 jours et accédé hier.

Cache partagé entre plusieurs sites

Si notre nginx fait tourner plusieurs sites il est préférable de déterminer également une clé de cache qui nous évitera les conflits.

http {
  proxy_cache_key "$scheme://$host$request_uri";
}

Configuration du vhost

Il nous reste maintenant uniquement à configurer le site en question.

  location /media {
    proxy_pass http://app;
    proxy_cache dragonfly;
    proxy_cache_valid 200 30d;
  }

Nous demandons donc à servir les fichiers ayant une URL débutant par /media par notre proxy_pass s’il ne sont pas en cache et de les y mettre.

La directive proxy_cache_valid nous permet de spécifier une durée de validité du cache par status de réponse, par exemple 30 jours pour une 200, 1 minute pour une 404 etc…

C’est tout pour cet article, j’espère qu’il vous aidera à rendre le web un peu plus rapide.

L’équipe Synbioz.

Libres d’être ensemble.