BLOG | NGINX

Guide de mise en cache avec NGINX et NGINX Plus

NGINX-Partie-de-F5-horiz-black-type-RGB
Vignette de Faisal Memon
Fayçal Memon
Publié le 23 juillet 2015

Nous savons tous que les performances des applications et des sites Web sont un facteur essentiel de leur succès. Cependant, le processus permettant d’améliorer les performances de votre application ou de votre site Web n’est pas toujours clair. La qualité du code et l’infrastructure sont bien sûr essentielles, mais dans de nombreux cas, vous pouvez apporter de vastes améliorations à l’expérience de l’utilisateur final de votre application en vous concentrant sur certaines techniques de livraison d’applications très basiques. Un tel exemple consiste à implémenter et à optimiser la mise en cache dans votre pile d’applications. Cet article de blog couvre les techniques qui peuvent aider les utilisateurs novices et avancés à obtenir de meilleures performances en utilisant les fonctionnalités de cache de contenu incluses dans NGINX et NGINX Plus.

Aperçu

Un cache de contenu se trouve entre un client et un « serveur d’origine » et enregistre des copies de tout le contenu qu’il voit. Si un client demande du contenu que le cache a stocké, il renvoie le contenu directement sans contacter le serveur d'origine. Cela améliore les performances car le cache de contenu est plus proche du client et utilise plus efficacement les serveurs d’applications car ils n’ont pas à effectuer le travail de génération de pages à partir de zéro à chaque fois.

Il existe potentiellement plusieurs caches entre le navigateur Web et le serveur d’applications : le cache du navigateur du client, les caches intermédiaires, les réseaux de diffusion de contenu (CDN) et l’équilibreur de charge ou le proxy inverse situé devant les serveurs d’applications. La mise en cache, même au niveau du proxy inverse/équilibreur de charge, peut considérablement améliorer les performances.

À titre d’exemple, l’année dernière, j’ai entrepris de régler les performances d’un site Web qui se chargeait lentement. L’une des premières choses que j’ai remarquées est qu’il fallait plus d’une seconde pour générer la page d’accueil principale. Après quelques débogages, j'ai découvert que, comme la page était marquée comme non cachable, elle était générée dynamiquement en réponse à chaque requête. La page elle-même ne changeait pas très souvent et n'était pas personnalisée, donc ce n'était pas nécessaire. À titre d’expérience, j’ai marqué la page d’accueil pour qu’elle soit mise en cache pendant 5 secondes par l’équilibreur de charge, et le simple fait de le faire a entraîné une amélioration notable. Le temps d’accès au premier octet est descendu à quelques millisecondes et la page s’est chargée visiblement plus rapidement.

NGINX est généralement déployé en tant que proxy inverse ou équilibreur de charge dans une pile d'applications et dispose d'un ensemble complet de fonctionnalités de mise en cache. La section suivante explique comment configurer la mise en cache de base avec NGINX.

Comment installer et configurer la mise en cache de base

Seules deux directives sont nécessaires pour activer la mise en cache de base : proxy_cache_path et proxy_cache . La directive proxy_cache_path définit le chemin et la configuration du cache, et la directive proxy_cache l'active.

proxy_cache_path /chemin/vers/cache niveaux=1:2 clés_zone=mon_cache:10m taille_max=10g inactif=60m use_temp_path=désactivé; serveur { # ... emplacement / { proxy_cache mon_cache; proxy_pass http://mon_stream; } }

Les paramètres de la directive proxy_cache_path définissent les paramètres suivants :

  • Le répertoire du disque local pour le cache s'appelle /path/to/cache/ .
  • levels établit une hiérarchie de répertoires à deux niveaux sous /path/to/cache/ . Avoir un grand nombre de fichiers dans un seul répertoire peut ralentir l’accès aux fichiers. Nous recommandons donc une hiérarchie de répertoires à deux niveaux pour la plupart des déploiements. Si le paramètre niveaux n'est pas inclus, NGINX place tous les fichiers dans le même répertoire.
  • keys_zone configure une zone de mémoire partagée pour stocker les clés de cache et les métadonnées telles que les minuteurs d'utilisation. Avoir une copie des clés en mémoire permet à NGINX de déterminer rapidement si une requête est un HIT ou un MISS sans avoir à aller sur le disque, ce qui accélère considérablement la vérification. Une zone de 1 Mo peut stocker des données pour environ 8 000 clés, donc la zone de 10 Mo configurée dans l'exemple peut stocker des données pour environ 80 000 clés.
  • max_size définit la limite supérieure de la taille du cache (à 10 gigaoctets dans cet exemple). C'est facultatif ; ne pas spécifier de valeur permet au cache de croître pour utiliser tout l'espace disque disponible. Lorsque la taille du cache atteint la limite, un processus appelé gestionnaire de cache supprime les fichiers les moins récemment utilisés pour ramener la taille du cache sous la limite.
  • inactif spécifie combien de temps un élément peut rester dans le cache sans être consulté. Dans cet exemple, un fichier qui n'a pas été demandé depuis 60 minutes est automatiquement supprimé du cache par le processus du gestionnaire de cache, qu'il ait expiré ou non. La valeur par défaut est de 10 minutes ( 10m ). Le contenu inactif diffère du contenu expiré. NGINX ne supprime pas automatiquement le contenu qui a expiré comme défini par un en-tête de contrôle de cache ( Cache-Control:max-age=120 par exemple). Le contenu expiré (obsolète) est supprimé uniquement s'il n'a pas été consulté pendant la durée spécifiée par inactive . Lorsqu'un contenu expiré est consulté, NGINX l'actualise à partir du serveur d'origine et réinitialise le minuteur d'inactivité .
  • NGINX écrit d’abord les fichiers destinés au cache dans une zone de stockage temporaire, et la directive use_temp_path=off demande à NGINX de les écrire dans les mêmes répertoires où ils seront mis en cache. Nous vous recommandons de définir ce paramètre sur off pour éviter la copie inutile de données entre les systèmes de fichiers. use_temp_path a été introduit dans NGINX version 1.7.10 et NGINX Plus R6 .

Et enfin, la directive proxy_cache active la mise en cache de tout le contenu qui correspond à l'URL du bloc d'emplacement parent (dans l'exemple, / ). Vous pouvez également inclure la directive proxy_cache dans un bloc de serveur ; elle s'applique à tous les blocs d'emplacement du serveur qui n'ont pas leur propre directive proxy_cache .

Diffusion de contenu mis en cache lorsque l'origine est en panne

Une fonctionnalité puissante de la mise en cache de contenu NGINX est que NGINX peut être configuré pour fournir du contenu obsolète à partir de son cache lorsqu'il ne peut pas obtenir de contenu nouveau à partir des serveurs d'origine. Cela peut se produire si tous les serveurs d'origine d'une ressource mise en cache sont en panne ou temporairement occupés. Plutôt que de relayer l’erreur au client, NGINX fournit la version obsolète du fichier à partir de son cache. Cela fournit un niveau supplémentaire de tolérance aux pannes pour les serveurs proxy NGINX et garantit la disponibilité en cas de pannes de serveur ou de pics de trafic. Pour activer cette fonctionnalité, incluez la directive proxy_cache_use_stale :

emplacement / { # ... proxy_cache_use_stale erreur délai d'attente http_500 http_502 http_503 http_504; }

Avec cet exemple de configuration, si NGINX reçoit une erreur , un délai d'attente ou l'une des erreurs 5xx spécifiées du serveur d'origine et qu'il dispose d'une version obsolète du fichier demandé dans son cache, il fournit le fichier obsolète au lieu de relayer l'erreur au client.

Ajustement du cache et amélioration des performances

NGINX dispose d’une multitude de paramètres facultatifs permettant d’affiner les performances du cache. Voici un exemple qui en active quelques-uns :

proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; serveur { # ... emplacement / { proxy_cache my_cache; proxy_cache_revalidate activé; proxy_cache_min_uses 3; proxy_cache_use_stale erreur timeout mise à jour http_500 http_502 http_503 http_504; proxy_cache_background_update activé; proxy_cache_lock activé; proxy_pass http://my_upstream; } }

Ces directives configurent le comportement suivant :

  • proxy_cache_revalidate indique à NGINX d'utiliser des requêtes GET conditionnelles lors de l'actualisation du contenu des serveurs d'origine. Si un client demande un élément mis en cache mais expiré comme défini par les en-têtes de contrôle du cache, NGINX inclut le champ If-Modified-Since dans l'en-tête de la requête GET qu'il envoie au serveur d'origine. Cela permet d'économiser de la bande passante, car le serveur envoie l'élément complet uniquement s'il a été modifié depuis l'heure enregistrée dans l'en-tête Last-Modified attaché au fichier lorsque NGINX l'a initialement mis en cache.
  • proxy_cache_min_uses définit le nombre de fois qu'un élément doit être demandé par les clients avant que NGINX le mette en cache. Cela est utile si le cache se remplit constamment, car cela garantit que seuls les éléments les plus fréquemment consultés sont ajoutés au cache. Par défaut, proxy_cache_min_uses est défini sur 1.
  • Le paramètre de mise à jour de la directive proxy_cache_use_stale , combiné à l'activation de la directive proxy_cache_background_update , indique à NGINX de fournir du contenu obsolète lorsque les clients demandent un élément expiré ou en cours de mise à jour à partir du serveur d'origine. Toutes les mises à jour seront effectuées en arrière-plan. Le fichier obsolète est renvoyé pour toutes les demandes jusqu'à ce que le fichier mis à jour soit entièrement téléchargé.
  • Avec proxy_cache_lock activé, si plusieurs clients demandent un fichier qui n'est pas à jour dans le cache (un MISS ), seule la première de ces demandes est autorisée à accéder au serveur d'origine. Les requêtes restantes attendent que cette requête soit satisfaite, puis extraient le fichier du cache. Sans proxy_cache_lock activé, toutes les requêtes entraînant des échecs de cache vont directement au serveur d'origine.

Répartition du cache sur plusieurs disques durs

Si vous disposez de plusieurs disques durs, NGINX peut être utilisé pour répartir le cache entre eux. Voici un exemple qui répartit les clients de manière égale sur deux disques durs en fonction de l'URI de la demande :

proxy_cache_path /chemin/vers/hdd1 niveaux=1:2 zones_clés=mon_cache_hdd1:10m taille_max=10g inactif=60m use_temp_path=désactivé ;
proxy_cache_path /chemin/vers/hdd2 niveaux=1:2 zones_clés=mon_cache_hdd2:10m
taille_max=10g inactif=60m use_temp_path=désactivé ;

split_clients $request_uri $my_cache {
50% « mon_cache_hdd1 » ;
50% « mon_cache_hdd2 » ;
}

serveur {
# ...
emplacement / {
proxy_cache $my_cache ;
proxy_pass http://mon_amont ;
}
}

Les deux directives proxy_cache_path définissent deux caches ( my_cache_hdd1 et my_cache_hdd2 ) sur deux disques durs différents. Le bloc de configuration split_clients spécifie que les résultats de la moitié des requêtes ( 50% ) sont mis en cache dans my_cache_hdd1 et l'autre moitié dans my_cache_hdd2 . Le hachage basé sur la variable $request_uri (l'URI de la requête) détermine quel cache est utilisé pour chaque requête, le résultat étant que les requêtes pour un URI donné sont toujours mises en cache dans le même cache.

Veuillez noter que cette approche ne remplace pas une configuration de disque dur RAID. En cas de panne du disque dur, cela peut entraîner un comportement imprévisible du système, notamment l'affichage de codes de réponse 500 pour les demandes dirigées vers le disque dur défaillant. Une configuration de disque dur RAID appropriée peut gérer les pannes de disque dur.

Questions fréquemment posées (FAQ)

Cette section répond à certaines questions fréquemment posées sur la mise en cache de contenu NGINX.

Le cache NGINX peut-il être instrumenté ?

Oui, avec la directive add_header :

ajouter_en-tête X-Cache-Status $upstream_cache_status;

Cet exemple ajoute un en-tête HTTP X-Cache-Status dans les réponses aux clients. Voici les valeurs possibles pour $upstream_cache_status :

  • MISS – La réponse n’a pas été trouvée dans le cache et a donc été récupérée à partir d’un serveur d’origine. La réponse a peut-être alors été mise en cache.
  • BYPASS – La réponse a été récupérée à partir du serveur d’origine au lieu d’être servie à partir du cache, car la demande correspondait à une directive proxy_cache_bypass (voir Puis-je percer un trou dans mon cache ? ci-dessous.) La réponse a peut-être alors été mise en cache.
  • EXPIRÉ – L’entrée dans le cache a expiré. La réponse contient du contenu nouveau provenant du serveur d’origine.
  • STALE – Le contenu est obsolète car le serveur d’origine ne répond pas correctement et proxy_cache_use_stale a été configuré.
  • MISE À JOUR – Le contenu est obsolète car l’entrée est actuellement en cours de mise à jour en réponse à une demande précédente et la mise à jour proxy_cache_use_stale est configurée.
  • REVALIDATED – La directive proxy_cache_revalidate a été activée et NGINX a vérifié que le contenu actuel mis en cache était toujours valide ( If-Modified-Since ou If-None-Match ).
  • HIT – La réponse contient du contenu valide et récent provenant directement du cache.

Comment NGINX détermine-t-il s’il faut ou non mettre quelque chose en cache ?

NGINX met en cache une réponse uniquement si le serveur d’origine inclut soit l’en-tête Expires avec une date et une heure dans le futur, soit l’en-tête Cache-Control avec la directive max-age définie sur une valeur différente de zéro.

Par défaut, NGINX respecte les autres directives dans l'en-tête Cache-Control : il ne met pas en cache les réponses lorsque l'en-tête inclut la directive Private , No-Cache ou No-Store . Il ne met pas non plus en cache les réponses avec l'en-tête Set-Cookie . De plus, il met en cache uniquement les réponses aux requêtes GET et HEAD . Vous pouvez remplacer ces valeurs par défaut comme décrit dans les réponses ci-dessous.

NGINX ne met pas en cache les réponses si proxy_buffering est défini sur off . Il est activé par défaut.

Les en-têtes de contrôle du cache peuvent-ils être ignorés ?

Oui, avec la directive proxy_ignore_headers . Par exemple, avec cette configuration :

emplacement /images/ { proxy_cache mon_cache; proxy_ignore_headers Cache-Control; proxy_cache_valid tout 30m; # ... }

NGINX ignore l'en-tête Cache-Control pour tout ce qui se trouve sous /images/ . La directive proxy_cache_valid impose une expiration pour les données mises en cache et est requise si les en-têtes Cache-Control sont ignorés. NGINX ne met pas en cache les fichiers qui n'ont pas de date d'expiration.

NGINX peut-il mettre en cache du contenu avec un cookie défini dans l'en-tête ?

Oui, avec la directive proxy_ignore_headers , comme indiqué dans la réponse précédente.

NGINX peut-il mettre en cache les requêtes POST ?

Oui, avec la directive proxy_cache_methods :

méthodes_proxy_cache OBTENIR LA PUBLICATION EN TÊTE ;

Cet exemple permet la mise en cache des requêtes POST .

NGINX peut-il mettre en cache du contenu dynamique ?

Oui, à condition que l'en-tête Cache-Control le permette. La mise en cache de contenu dynamique, même pendant une courte période, peut réduire la charge sur les serveurs d'origine et les bases de données, ce qui améliore le temps d'obtention du premier octet, car la page n'a pas besoin d'être régénérée pour chaque demande.

Puis-je percer un trou dans ma cache ?

Oui, avec la directive proxy_cache_bypass :

emplacement / { proxy_cache_bypass $cookie_nocache $arg_nocache; # ... }

La directive définit les types de requêtes pour lesquels NGINX demande immédiatement du contenu au serveur d'origine au lieu d'essayer de le trouver d'abord dans le cache. C’est ce qu’on appelle parfois « percer un trou » dans la cache. Dans cet exemple, NGINX le fait pour les requêtes avec un cookie ou un argument nocache , par exemple http://www.example.com/?nocache=true . NGINX peut toujours mettre en cache la réponse résultante pour les futures demandes qui ne sont pas contournées.

Quelle clé de cache NGINX utilise-t-il ?

La forme par défaut des clés générées par NGINX est similaire à un hachage MD5 des variables NGINX suivantes : $scheme$proxy_host$request_uri ; l'algorithme réel utilisé est légèrement plus compliqué.

proxy_cache_path /chemin/vers/cache niveaux=1:2 clés_zone=mon_cache:10m taille_max=10g inactif=60m use_temp_path=désactivé ;

serveur {
# ...
emplacement / {
proxy_cache mon_cache ;
proxy_pass http://mon_amont ;
}
}

Pour cet exemple de configuration, la clé de cache pour http://www.example.org/my_image.jpg est calculée comme md5(“http://my_upstream:80/my_image.jpg”) .

Notez que la variable $proxy_host est utilisée dans la valeur hachée au lieu du nom d'hôte réel ( www.example.com ). $proxy_host est défini comme le nom et le port du serveur proxy comme spécifié dans la directive proxy_pass .

Pour modifier les variables (ou autres termes) utilisées comme base pour la clé, utilisez la directive proxy_cache_key (voir également la question suivante).

Puis-je utiliser un cookie dans le cadre de ma clé de cache ?

Oui, la clé de cache peut être configurée pour être n'importe quelle valeur arbitraire, par exemple :

clé_cache_proxy $proxy_host $request_uri $cookie_jessionid;

Cet exemple intègre la valeur du cookie JSESSIONID dans la clé de cache. Les éléments avec le même URI mais des valeurs JSESSIONID différentes sont mis en cache séparément en tant qu'éléments uniques.

NGINX utilise-t-il l'en-tête ETag ?

Dans NGINX 1.7.3 et NGINX Plus R5 et versions ultérieures, l'en-tête ETag est entièrement pris en charge avec If-None-Match .

Comment NGINX gère-t-il les demandes de plage d’octets ?

Si le fichier est à jour dans le cache, NGINX honore une demande de plage d’octets et fournit uniquement les octets spécifiés de l’élément au client. Si le fichier n’est pas mis en cache ou s’il est obsolète, NGINX télécharge l’intégralité du fichier à partir du serveur d’origine. Si la demande concerne une plage d'octets unique, NGINX envoie cette plage au client dès qu'elle est rencontrée dans le flux de téléchargement. Si la demande spécifie plusieurs plages d'octets dans le même fichier, NGINX fournit le fichier entier au client une fois le téléchargement terminé.

Une fois le téléchargement terminé, NGINX déplace l’intégralité de la ressource dans le cache afin que toutes les futures demandes de plage d’octets, qu’il s’agisse d’une plage unique ou de plusieurs plages, soient satisfaites immédiatement à partir du cache.

Veuillez noter que le serveur en amont doit prendre en charge les demandes de plage d'octets pour que NGINX honore les demandes de plage d'octets adressées à ce serveur en amont .

NGINX prend-il en charge la purge du cache ?

NGINX Plus prend en charge la purge sélective des fichiers mis en cache. Ceci est utile si un fichier a été mis à jour sur le serveur d'origine mais est toujours valide dans le cache NGINX Plus (le Cache-Control:max-age est toujours valide et le délai d'expiration défini par le paramètre inactive de la directive proxy_cache_path n'a pas expiré). Avec la fonction de purge du cache de NGINX Plus, ce fichier peut être facilement supprimé. Pour plus de détails, voir Purge du contenu du cache .

Comment NGINX gère-t-il l'en-tête Pragma ?

L'en-tête Pragma:no-cache est ajouté par les clients pour contourner tous les caches intermédiaires et accéder directement au serveur d'origine pour le contenu demandé. NGINX ne respecte pas l'en-tête Pragma par défaut, mais vous pouvez configurer la fonctionnalité avec la directive proxy_cache_bypass suivante :

emplacement /images/ { proxy_cache mon_cache; proxy_cache_bypass $http_pragma; # ... }

NGINX prend-il en charge les extensions stale-while-revalidate et stale-if-error de l'en-tête Cache-Control ?

Oui, dans NGINX Plus R12 et NGINX 1.11.10 et versions ultérieures. À quoi servent ces extensions :

  • L'extension stale-while-revalidate de l'en-tête HTTP Cache-Control permet d'utiliser une réponse mise en cache obsolète si elle est en cours de mise à jour.
  • L'extension stale-if-error de l'en-tête HTTP Cache-Control permet d'utiliser une réponse mise en cache obsolète en cas d'erreur.

Ces en-têtes ont une priorité inférieure à la directive proxy_cache_use_stale décrite ci-dessus.

NGINX prend-il en charge l'en-tête Vary ?

Oui, dans NGINX Plus R5 et NGINX 1.7.7 et versions ultérieures. Voici un bon aperçu de l'en-tête Vary .

Lectures complémentaires

Il existe de nombreuses autres façons de personnaliser et d’ajuster la mise en cache NGINX. Pour en savoir plus sur la mise en cache avec NGINX, veuillez consulter les ressources suivantes :


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."