srcache: Mise en cache transparente basée sur des sous-requêtes pour des emplacements NGINX arbitraires
Installation
Vous pouvez installer ce module dans n'importe quelle distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-srcache
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-srcache
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_http_srcache_filter_module.so;
Ce document décrit nginx-module-srcache v0.32 publié le 28 juin 2022.
upstream my_memcached {
server 10.62.136.7:11211;
keepalive 10;
}
location = /memc {
internal;
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
memc_ignore_client_abort on;
set $memc_key $query_string;
set $memc_exptime 300;
memc_pass my_memcached;
}
location /foo {
set $key $uri$args;
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
srcache_store_statuses 200 301 302 307 308;
# proxy_pass/fastcgi_pass/drizzle_pass/echo/etc...
# ou même des fichiers statiques sur le disque
}
location = /memc2 {
internal;
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
memc_ignore_client_abort on;
set_unescape_uri $memc_key $arg_key;
set $memc_exptime $arg_exptime;
memc_pass unix:/tmp/memcached.sock;
}
location /bar {
set_escape_uri $key $uri$args;
srcache_fetch GET /memc2 key=$key;
srcache_store PUT /memc2 key=$key&exptime=$srcache_expire;
# proxy_pass/fastcgi_pass/drizzle_pass/echo/etc...
# ou même des fichiers statiques sur le disque
}
map $request_method $skip_fetch {
default 0;
POST 1;
PUT 1;
}
server {
listen 8080;
location /api/ {
set $key "$uri?$args";
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
srcache_methods GET PUT POST;
srcache_fetch_skip $skip_fetch;
# proxy_pass/drizzle_pass/content_by_lua/echo/...
}
}
Description
Ce module fournit une couche de mise en cache transparente pour des emplacements nginx arbitraires (comme ceux utilisant un upstream ou même servant des fichiers statiques sur disque). Le comportement de mise en cache est principalement compatible avec RFC 2616.
En général, le memc-nginx-module est utilisé avec ce module pour fournir un backend de stockage de cache concret. Mais techniquement, n'importe quel module qui fournit une interface REST peut être utilisé comme les sous-requêtes de récupération et de stockage utilisées par ce module.
Pour les requêtes principales, la directive srcache_fetch fonctionne à la fin de la phase d'accès, donc les directives allow et deny du module d'accès standard s'exécutent avant les nôtres, ce qui est généralement le comportement souhaité pour des raisons de sécurité.
Le flux de travail de ce module ressemble à ceci :

Mise en cache des sous-requêtes
Pour les sous-requêtes, nous interdisons explicitement l'utilisation de ce module car il est trop difficile à bien gérer. Il y avait une implémentation, mais elle était boguée et j'ai finalement abandonné la réparation et l'ai abandonnée.
Cependant, si vous utilisez le lua-nginx-module, il est facile de faire de la mise en cache de sous-requêtes en Lua par vous-même. C'est-à-dire, d'abord émettre une sous-requête à un emplacement memc-nginx-module pour effectuer une recherche de cache explicite, si le cache est trouvé, utilisez simplement les données mises en cache retournées ; sinon, revenez au véritable backend, et enfin effectuez une insertion de cache pour alimenter les données dans le cache.
Utiliser ce module pour la mise en cache des requêtes principales et Lua pour la mise en cache des sous-requêtes est l'approche que nous adoptons dans notre entreprise. Cette solution hybride fonctionne très bien en production.
Mise en cache Memcached distribuée
Voici un exemple simple démontrant un mécanisme de mise en cache Memcached distribué construit sur ce module. Supposons que nous avons trois nœuds Memcached différents et que nous utilisons un simple modulo pour hacher nos clés.
http {
upstream moon {
server 10.62.136.54:11211;
server unix:/tmp/memcached.sock backup;
}
upstream earth {
server 10.62.136.55:11211;
}
upstream sun {
server 10.62.136.56:11211;
}
upstream_list universe moon earth sun;
server {
memc_connect_timeout 100ms;
memc_send_timeout 100ms;
memc_read_timeout 100ms;
location = /memc {
internal;
set $memc_key $query_string;
set_hashed_upstream $backend universe $memc_key;
set $memc_exptime 3600; # en secondes
memc_pass $backend;
}
location / {
set $key $uri;
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
# proxy_pass/fastcgi_pass/content_by_lua/drizzle_pass/...
}
}
}
moon, earth et sun. Ce sont nos trois serveurs Memcached.
2. Ensuite, nous les regroupons en tant qu'entité de liste upstream nommée universe avec la directive upstream_list fournie par set-misc-nginx-module.
3. Après cela, nous définissons un emplacement interne nommé /memc pour communiquer avec le cluster Memcached.
4. Dans cet emplacement /memc, nous définissons d'abord la variable $memc_key avec la chaîne de requête ($args), puis utilisons la directive set_hashed_upstream pour hacher notre $memc_key sur la liste upstream universe, afin d'obtenir un nom upstream concret à attribuer à la variable $backend.
5. Nous passons cette variable $backend à la directive memc_pass. La variable $backend peut contenir une valeur parmi moon, earth et sun.
6. De plus, nous définissons le temps d'expiration de mise en cache Memcached à 3600 secondes (c'est-à-dire une heure) en remplaçant la variable $memc_exptime.
7. Dans notre emplacement public principal /, nous configurons la variable $uri comme notre clé de cache, puis configurons srcache_fetch pour les recherches de cache et srcache_store pour les mises à jour de cache. Nous utilisons deux sous-requêtes vers notre emplacement /memc défini précédemment dans ces deux directives.
On peut utiliser les directives set_by_lua ou rewrite_by_lua du lua-nginx-module pour injecter du code Lua personnalisé afin de calculer les variables $backend et/ou $key dans l'exemple ci-dessus.
Une chose à prendre en compte est que Memcached a des restrictions sur les longueurs de clé, c'est-à-dire 250 octets, donc pour les clés qui peuvent être très longues, on peut utiliser la directive set_md5 ou ses amis pour pré-hacher la clé à un résumé de longueur fixe avant de l'assigner à $memc_key dans l'emplacement /memc ou similaire.
De plus, on peut utiliser les directives srcache_fetch_skip et srcache_store_skip pour contrôler ce qu'il faut mettre en cache et ce qu'il ne faut pas sur une base par requête, et Lua peut également être utilisé ici de manière similaire. Ainsi, la possibilité est vraiment illimitée.
Pour maximiser la vitesse, nous activons souvent le pool de connexions TCP (ou Unix Domain Socket) pour nos upstreams Memcached fournis par HttpUpstreamKeepaliveModule, par exemple,
upstream moon {
server 10.62.136.54:11211;
server unix:/tmp/memcached.sock backup;
keepalive 10;
}
où nous définissons un pool de connexions qui maintient jusqu'à 10 connexions keep-alive (par processus de travail nginx) pour notre upstream moon (cluster).
Mise en cache avec Redis
Redis est un magasin de clés-valeurs alternatif avec de nombreuses fonctionnalités supplémentaires.
Voici un exemple fonctionnel utilisant le module lua-resty-redis :
location ~ '\.php$|^/update.php' {
# configuration de cache
set $key $request_uri;
try_files $uri =404;
srcache_fetch_skip $skip_cache;
srcache_store_skip $skip_cache;
srcache_response_cache_control off;
srcache_store_statuses 200 201 301 302 307 308 404 503;
set_escape_uri $escaped_key $key;
srcache_fetch GET /redis-fetch $key;
srcache_store PUT /redis-store key=$escaped_key;
more_set_headers 'X-Cache-Fetch-Status $srcache_fetch_status';
more_set_headers 'X-Cache-Store-Status $srcache_store_status';
fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
# Remarque de sécurité : Si vous exécutez une version de PHP antérieure à la
# dernière 5.3, vous devez avoir "cgi.fix_pathinfo = 0;" dans php.ini.
# Voir http://serverfault.com/q/627903/94922 pour plus de détails.
include fastcgi_params;
# Bloquer les attaques httproxy. Voir https://httpoxy.org/.
fastcgi_param HTTP_PROXY "";
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_intercept_errors on;
fastcgi_pass upstream-name;
}
location /redis-fetch {
internal;
resolver 8.8.8.8 valid=300s;
resolver_timeout 10s;
content_by_lua_block {
local key = assert(ngx.var.request_uri, "no key found")
local redis = require "resty.redis"
local red, err = redis:new()
if not red then
ngx.log(ngx.ERR, "Échec de la création de la variable redis, erreur -> ", err)
ngx.exit(500)
end
assert(red:connect("redis-master.default.svc.cluster.local", 6379))
if not red then
ngx.log(ngx.ERR, "Échec de la connexion à redis, erreur -> ", err)
ngx.exit(500)
end
local res, err = red:auth("redispassword")
if not res then
ngx.say("échec de l'authentification, ", err)
ngx.exit(500)
end
local data = assert(red:get(key))
assert(red:set_keepalive(10000, 100))
if res == ngx.null then
return ngx.exit(404)
end
ngx.print(data)
}
}
location /redis-store {
internal;
resolver 8.8.8.8 valid=300s;
resolver_timeout 10s;
content_by_lua_block {
local value = assert(ngx.req.get_body_data(), "no value found")
local key = assert(ngx.var.request_uri, "no key found")
local redis = require "resty.redis"
local red, err = redis:new()
if not red then
ngx.log(ngx.ERR, "Échec de la création de la variable redis, erreur -> ", err)
ngx.exit(500)
end
assert(red:connect("redis-master.default.svc.cluster.local", 6379))
if not red then
ngx.log(ngx.ERR, "Échec de la connexion à redis, erreur -> ", err)
ngx.exit(500)
end
local res, err = red:auth("redispassword")
if not res then
ngx.say("échec de l'authentification, ", err)
ngx.exit(500)
end
local data = assert(red:set(key, value))
assert(red:set_keepalive(10000, 100))
if res == ngx.null then
return ngx.exit(404)
end
}
}
Voici un exemple fonctionnel utilisant les modules HTTPRedis (fetch) et Redis2 (store) :
location /api {
default_type text/css;
set $key $uri;
set_escape_uri $escaped_key $key;
srcache_fetch GET /redis $key;
srcache_store PUT /redis2 key=$escaped_key&exptime=120;
# fastcgi_pass/proxy_pass/drizzle_pass/postgres_pass/echo/etc
}
location = /redis {
internal;
set_md5 $redis_key $args;
redis_pass 127.0.0.1:6379;
}
location = /redis2 {
internal;
set_unescape_uri $exptime $arg_exptime;
set_unescape_uri $key $arg_key;
set_md5 $key;
redis2_query set $key $echo_request_body;
redis2_query expire $key $exptime;
redis2_pass 127.0.0.1:6379;
}
Cet exemple utilise la variable $echo_request_body fournie par echo-nginx-module. Notez que vous avez besoin de la dernière version de echo-nginx-module, v0.38rc2 car les versions antérieures peuvent ne pas fonctionner de manière fiable.
De plus, vous avez besoin des modules HttpRedisModule et redis2-nginx-module. Le premier est utilisé dans la sous-requête srcache_fetch et le second est utilisé dans la sous-requête srcache_store.
Le noyau Nginx a également un bug qui pourrait empêcher le support du pipelining de redis2-nginx-module de fonctionner correctement dans certaines conditions extrêmes. Et le patch suivant corrige cela :
http://mailman.nginx.org/pipermail/nginx-devel/2012-March/002040.html
Notez que, cependant, si vous utilisez le bundle OpenResty 1.0.15.3 ou ultérieur, alors vous avez déjà tout ce dont vous avez besoin ici dans le bundle.
Prétraitement des clés de cache
Il est souvent souhaitable de prétraiter la clé de cache pour exclure les bruits aléatoires qui pourraient nuire au taux de réussite du cache. Par exemple, les identifiants de session aléatoires dans les arguments URI doivent généralement être supprimés.
Considérons la chaîne de requête URI suivante
SID=BC3781C3-2E02-4A11-89CF-34E5CFE8B0EF&UID=44332&L=EN&M=1&H=1&UNC=0&SRC=LK&RT=62
nous voulons supprimer les arguments SID et UID. Il est facile d'y parvenir si vous utilisez lua-nginx-module en même temps :
location = /t {
rewrite_by_lua '
local args = ngx.req.get_uri_args()
args.SID = nil
args.UID = nil
ngx.req.set_uri_args(args)
';
echo $args;
}
Ici, nous utilisons la directive echo du echo-nginx-module pour afficher la valeur finale de $args à la fin. Vous pouvez la remplacer par vos configurations srcache-nginx-module et configurations upstream à la place pour votre cas. Testons cette interface /t avec curl :
$ curl 'localhost:8081/t?RT=62&SID=BC3781C3-2E02-4A11-89CF-34E5CFE8B0EF&UID=44332&L=EN&M=1&H=1&UNC=0&SRC=LK'
M=1&UNC=0&RT=62&H=1&L=EN&SRC=LK
Il convient de mentionner que, si vous souhaitez conserver l'ordre des arguments URI, vous pouvez effectuer des substitutions de chaînes sur la valeur de $args directement, par exemple,
location = /t {
rewrite_by_lua '
local args = ngx.var.args
newargs, n, err = ngx.re.gsub(args, [[\b[SU]ID=[^&]*&?]], "", "jo")
if n and n > 0 then
ngx.var.args = newargs
end
';
echo $args;
}
Testez-le à nouveau avec la commande curl d'origine, nous obtenons exactement ce que nous attendions :
RT=62&L=EN&M=1&H=1&UNC=0&SRC=LK
Mais pour des raisons de mise en cache, il est bon de normaliser l'ordre des arguments URI afin d'augmenter le taux de réussite du cache. Et l'ordre des entrées de la table de hachage utilisée par LuaJIT ou Lua peut être utilisé pour normaliser l'ordre comme un effet secondaire agréable.
Directives
srcache_fetch
syntax: srcache_fetch <method> <uri> <args>?
default: no
context: http, server, location, location if
phase: post-access
Cette directive enregistre un gestionnaire de phase d'accès qui émettra une sous-requête Nginx pour rechercher dans le cache.
Lorsque la sous-requête retourne un code d'état autre que 200, un échec de cache est signalé et le flux de contrôle continuera vers les phases ultérieures, y compris la phase de contenu configurée par ngx_http_proxy_module, ngx_http_fastcgi_module, et d'autres. Si la sous-requête retourne 200 OK, alors un succès de cache est signalé et ce module enverra la réponse de la sous-requête comme réponse de la requête principale actuelle au client directement.
Cette directive s'exécute toujours à la fin de la phase d'accès, de sorte que ngx_http_access_module's allow et deny s'exécuteront toujours avant celle-ci.
Vous pouvez utiliser la directive srcache_fetch_skip pour désactiver sélectivement la recherche dans le cache.
srcache_fetch_skip
syntax: srcache_fetch_skip <flag>
default: srcache_fetch_skip 0
context: http, server, location, location if
phase: post-access
L'argument <flag> prend en charge les variables nginx. Lorsque la valeur de cet argument n'est pas vide et n'est pas égale à 0, le processus de récupération sera inconditionnellement ignoré.
Par exemple, pour ignorer les requêtes de mise en cache qui ont un cookie nommé foo avec la valeur bar, nous pouvons écrire
location / {
set $key ...;
set_by_lua $skip '
if ngx.var.cookie_foo == "bar" then
return 1
end
return 0
';
srcache_fetch_skip $skip;
srcache_store_skip $skip;
srcache_fetch GET /memc $key;
srcache_store GET /memc $key;
# proxy_pass/fastcgi_pass/content_by_lua/...
}
$skip à la phase de réécriture (plus tôt). De même, la variable $key peut être calculée par Lua en utilisant la directive set_by_lua ou rewrite_by_lua également.
La directive standard map peut également être utilisée pour calculer la valeur de la variable $skip utilisée dans l'exemple ci-dessus :
map $cookie_foo $skip {
default 0;
bar 1;
}
mais votre déclaration map doit être placée dans le bloc de configuration http de votre fichier nginx.conf.
srcache_store
syntax: srcache_store <method> <uri> <args>?
default: no
context: http, server, location, location if
phase: output-filter
Cette directive enregistre un gestionnaire de filtre de sortie qui émettra une sous-requête Nginx pour enregistrer la réponse de la requête principale actuelle dans un backend de cache. Le code d'état de la sous-requête sera ignoré.
Vous pouvez utiliser les directives srcache_store_skip et srcache_store_max_size pour désactiver la mise en cache pour certaines requêtes en cas d'échec de cache.
Depuis la version v0.12rc7, la ligne d'état de réponse, les en-têtes de réponse et les corps de réponse seront tous mis en cache. Par défaut, les en-têtes de réponse spéciaux suivants ne seront pas mis en cache :
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
- Set-Cookie
Vous pouvez utiliser les directives srcache_store_pass_header et/ou srcache_store_hide_header pour contrôler quels en-têtes mettre en cache et lesquels ne pas.
Les morceaux de données de la réponse d'origine sont émis dès qu'ils arrivent. srcache_store se contente de copier et de collecter les données dans un filtre de sortie sans les retarder pour être envoyées en aval.
Mais veuillez noter que même si toutes les données de réponse seront envoyées immédiatement, la durée de vie de la requête Nginx actuelle ne se terminera pas tant que la sous-requête srcache_store n'est pas terminée. Cela signifie un retard dans la fermeture de la connexion TCP du côté serveur (lorsque HTTP keepalive est désactivé, mais les clients HTTP appropriés devraient fermer la connexion activement du côté client, ce qui n'ajoute aucun retard supplémentaire ni d'autres problèmes) ou le service de la prochaine requête envoyée sur la même connexion TCP (lorsque HTTP keepalive est en action).
srcache_store_max_size
syntax: srcache_store_max_size <size>
default: srcache_store_max_size 0
context: http, server, location, location if
phase: output-header-filter
Lorsque la longueur du corps de réponse dépasse cette taille, ce module ne tentera pas de stocker le corps de réponse dans le cache en utilisant le modèle de sous-requête spécifié dans srcache_store.
Ceci est particulièrement utile lors de l'utilisation d'un backend de stockage de cache qui a une limite supérieure stricte sur les données d'entrée. Par exemple, le serveur Memcached a une limite par défaut de 1 Mo par élément.
Lorsque 0 est spécifié (la valeur par défaut), il n'y a aucune vérification de limite.
srcache_store_skip
syntax: srcache_store_skip <flag>
default: srcache_store_skip 0
context: http, server, location, location if
phase: output-header-filter
L'argument <flag> prend en charge les variables Nginx. Lorsque la valeur de cet argument n'est pas vide et n'est pas égale à 0, le processus de stockage sera inconditionnellement ignoré.
À partir de la version v0.25, l'expression <flag> (pouvant contenir des variables Nginx) peut être évaluée jusqu'à deux fois : la première fois est juste après l'envoi de l'en-tête de réponse et lorsque l'expression <flag> n'est pas évaluée à des valeurs vraies, elle sera évaluée à nouveau juste après la fin du flux de données du corps de réponse. Avant v0.25, seule la première évaluation était effectuée.
Voici un exemple utilisant Lua pour définir $nocache afin d'éviter de stocker les URI contenant la chaîne "/tmp" :
set_by_lua $nocache '
if string.match(ngx.var.uri, "/tmp") then
return 1
end
return 0';
srcache_store_skip $nocache;
srcache_store_statuses
syntax: srcache_store_statuses <status1> <status2> ..
default: srcache_store_statuses 200 301 302 307 308
context: http, server, location, location if
phase: output-header-filter
Cette directive contrôle quelles réponses stocker dans le cache selon leur code d'état.
Par défaut, seules les réponses 200, 301, 302, 307 et 308 seront stockées dans le cache et toutes les autres réponses ignoreront srcache_store.
Vous pouvez spécifier des nombres positifs arbitraires pour le code d'état de réponse que vous souhaitez mettre en cache, y compris des codes d'erreur comme 404 et 503. Par exemple :
srcache_store_statuses 200 201 301 302 307 308 404 503;
Au moins un argument doit être donné à cette directive.
Cette directive a été introduite pour la première fois dans la version v0.13rc2.
srcache_store_ranges
syntax: srcache_store_ranges on|off
default: srcache_store_ranges off
context: http, server, location, location if
phase: output-body-filter
Lorsque cette directive est activée (par défaut à off), srcache_store stockera également les réponses 206 Partial Content générées par le module standard ngx_http_range_filter_module. Si vous activez cette directive, vous DEVEZ ajouter $http_range à vos clés de cache. Par exemple,
location / {
set $key "$uri$args$http_range";
srcache_fetch GET /memc $key;
srcache_store PUT /memc $key;
}
Cette directive a été introduite pour la première fois dans la version v0.27.
srcache_header_buffer_size
syntax: srcache_header_buffer_size <size>
default: srcache_header_buffer_size 4k/8k
context: http, server, location, location if
phase: output-header-filter
Cette directive contrôle le tampon d'en-tête lors de la sérialisation des en-têtes de réponse pour srcache_store. La taille par défaut est la taille de la page, généralement 4k ou 8k selon les plateformes spécifiques.
Notez que le tampon n'est pas utilisé pour contenir tous les en-têtes de réponse, mais juste chaque en-tête individuel. Donc, le tampon doit simplement être suffisamment grand pour contenir le plus long en-tête de réponse.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_store_hide_header
syntax: srcache_store_hide_header <header>
default: no
context: http, server, location, location if
phase: output-header-filter
Par défaut, ce module met en cache tous les en-têtes de réponse sauf les suivants :
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
- Set-Cookie
Vous pouvez cacher encore plus d'en-têtes de réponse de srcache_store en énumérant leurs noms (insensibles à la casse) par le biais de cette directive. Par exemple,
srcache_store_hide_header X-Foo;
srcache_store_hide_header Last-Modified;
Plusieurs occurrences de cette directive sont autorisées dans un seul emplacement.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
Voir aussi srcache_store_pass_header.
srcache_store_pass_header
syntax: srcache_store_pass_header <header>
default: no
context: http, server, location, location if
phase: output-header-filter
Par défaut, ce module met en cache tous les en-têtes de réponse sauf les suivants :
- Connection
- Keep-Alive
- Proxy-Authenticate
- Proxy-Authorization
- TE
- Trailers
- Transfer-Encoding
- Upgrade
- Set-Cookie
Vous pouvez forcer srcache_store à stocker un ou plusieurs de ces en-têtes de réponse de srcache_store en énumérant leurs noms (insensibles à la casse) par le biais de cette directive. Par exemple,
srcache_store_pass_header Set-Cookie;
srcache_store_pass_header Proxy-Autenticate;
Plusieurs occurrences de cette directive sont autorisées dans un seul emplacement.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
Voir aussi srcache_store_hide_header.
srcache_methods
syntax: srcache_methods <method>...
default: srcache_methods GET HEAD
context: http, server, location
phase: post-access, output-header-filter
Cette directive spécifie les méthodes de requête HTTP qui sont considérées par srcache_fetch ou srcache_store. Les méthodes de requête HTTP non listées seront complètement ignorées du cache.
Les méthodes HTTP suivantes sont autorisées : GET, HEAD, POST, PUT, et DELETE. Les méthodes GET et HEAD sont toujours implicitement incluses dans la liste, quelle que soit leur présence dans cette directive.
Notez que depuis la version v0.17, les requêtes HEAD sont toujours ignorées par srcache_store car leurs réponses ne contiennent jamais de corps de réponse.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_ignore_content_encoding
syntax: srcache_ignore_content_encoding on|off
default: srcache_ignore_content_encoding off
context: http, server, location, location if
phase: output-header-filter
Lorsque cette directive est désactivée (ce qui est la valeur par défaut), un en-tête de réponse Content-Encoding non vide entraînera srcache_store à ignorer le stockage de l'ensemble de la réponse dans le cache et à émettre un avertissement dans le fichier error.log de nginx comme ceci :
[warn] 12500#0: *1 srcache_store skipped due to response header "Content-Encoding: gzip"
(maybe you forgot to disable compression on the backend?)
Activer cette directive ignorera l'en-tête de réponse Content-Encoding et stockera la réponse comme d'habitude (et sans avertissement).
Il est recommandé de toujours désactiver la compression gzip/deflate sur votre serveur backend en spécifiant la ligne suivante dans votre fichier nginx.conf :
proxy_set_header Accept-Encoding "";
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_request_cache_control
syntax: srcache_request_cache_control on|off
default: srcache_request_cache_control off
context: http, server, location
phase: post-access, output-header-filter
Lorsque cette directive est activée, les en-têtes de requête Cache-Control et Pragma seront respectés par ce module de la manière suivante :
- srcache_fetch, c'est-à-dire l'opération de recherche dans le cache, sera ignorée lorsque les en-têtes de requête
Cache-Control: no-cacheet/ouPragma: no-cachesont présents. - srcache_store, c'est-à-dire l'opération de stockage dans le cache, sera ignorée lorsque l'en-tête de requête
Cache-Control: no-storeest spécifié.
Désactiver cette directive désactivera cette fonctionnalité et est considérée comme plus sûre pour les sites très fréquentés s'appuyant principalement sur le cache pour la vitesse.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
Voir aussi srcache_response_cache_control.
srcache_response_cache_control
syntax: srcache_response_cache_control on|off
default: srcache_response_cache_control on
context: http, server, location
phase: output-header-filter
Lorsque cette directive est activée, les en-têtes de réponse Cache-Control et Expires seront respectés par ce module de la manière suivante :
Cache-Control: privateignore srcache_store,Cache-Control: no-storeignore srcache_store,Cache-Control: no-cacheignore srcache_store,Cache-Control: max-age=0ignore srcache_store,- et
Expires: <date-no-more-recently-than-now>ignore srcache_store.
Cette directive a priorité sur les directives srcache_store_no_store, srcache_store_no_cache, et srcache_store_private.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
Voir aussi srcache_request_cache_control.
srcache_store_no_store
syntax: srcache_store_no_store on|off
default: srcache_store_no_store off
context: http, server, location
phase: output-header-filter
Activer cette directive forcera les réponses avec l'en-tête Cache-Control: no-store à être stockées dans le cache lorsque srcache_response_cache_control est activé et d'autres conditions sont remplies. Par défaut, c'est off.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_store_no_cache
syntax: srcache_store_no_cache on|off
default: srcache_store_no_cache off
context: http, server, location
phase: output-header-filter
Activer cette directive forcera les réponses avec l'en-tête Cache-Control: no-cache à être stockées dans le cache lorsque srcache_response_cache_control est activé et d'autres conditions sont remplies. Par défaut, c'est off.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_store_private
syntax: srcache_store_private on|off
default: srcache_store_private off
context: http, server, location
phase: output-header-filter
Activer cette directive forcera les réponses avec l'en-tête Cache-Control: private à être stockées dans le cache lorsque srcache_response_cache_control est activé et d'autres conditions sont remplies. Par défaut, c'est off.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_default_expire
syntax: srcache_default_expire <time>
default: srcache_default_expire 60s
context: http, server, location, location if
phase: output-header-filter
Cette directive contrôle la période d'expiration par défaut qui est autorisée pour la valeur de la variable $srcache_expire lorsque ni Cache-Control: max-age=N ni Expires ne sont spécifiés dans les en-têtes de réponse.
Les valeurs d'argument <time> sont en secondes par défaut. Mais il est sage de toujours spécifier explicitement l'unité de temps pour éviter toute confusion. Les unités de temps prises en charge sont "s" (secondes), "ms" (millisecondes), "y" (années), "M" (mois), "w" (semaines), "d" (jours), "h" (heures) et "m" (minutes). Par exemple,
srcache_default_expire 30m; # 30 minutes
Ce temps doit être inférieur à 597 heures.
La sémantique d'un temps d'expiration zéro dépend du backend de cache de stockage que vous utilisez actuellement, qui est indifférent à ce module. Dans le cas de Memcached, par exemple, les temps d'expiration zéro signifient que l'élément ne expirera jamais.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
srcache_max_expire
syntax: srcache_max_expire <time>
default: srcache_max_expire 0
context: http, server, location, location if
phase: output-header-filter
Cette directive contrôle la période d'expiration maximale qui est autorisée pour la valeur de la variable $srcache_expire. Ce paramètre a priorité sur d'autres méthodes de calcul.
Les valeurs d'argument <time> sont en secondes par défaut. Mais il est sage de toujours spécifier explicitement l'unité de temps pour éviter toute confusion. Les unités de temps prises en charge sont "s" (secondes), "ms" (millisecondes), "y" (années), "M" (mois), "w" (semaines), "d" (jours), "h" (heures) et "m" (minutes). Par exemple,
srcache_max_expire 2h; # 2 heures
Ce temps doit être inférieur à 597 heures.
Lorsque 0 est spécifié, ce qui est le paramètre par défaut, il n'y aura aucune limite.
Cette directive a été introduite pour la première fois dans la version v0.12rc7.
Variables
$srcache_expire
type: integer
cacheable: no
writable: no
Cette variable Nginx donne la période d'expiration recommandée (en secondes) pour la réponse actuelle étant stockée dans le cache. L'algorithme de calcul de la valeur est le suivant :
- Lorsque l'en-tête de réponse
Cache-Control: max-age=Nest spécifié, alorsNsera utilisé comme temps d'expiration, - sinon, si l'en-tête de réponse
Expiresest spécifié, alors le temps d'expiration sera obtenu en soustrayant l'horodatage actuel du temps spécifié dans l'en-têteExpires, - lorsque ni les en-têtes
Cache-Control: max-age=NniExpiresne sont spécifiés, utilisez la valeur spécifiée dans la directive srcache_default_expire.
La valeur finale de cette variable sera la valeur spécifiée par la directive srcache_max_expire si la valeur obtenue dans l'algorithme ci-dessus dépasse la valeur maximale (le cas échéant).
Vous n'avez pas à utiliser cette variable pour le temps d'expiration.
Cette variable a été introduite pour la première fois dans la version v0.12rc7.
$srcache_fetch_status
type: string
cacheable: no
writable: no
Cette variable Nginx est évaluée au statut de la phase "fetch" pour le système de mise en cache. Trois valeurs sont possibles, HIT, MISS, et BYPASS.
Lorsque la sous-requête "fetch" retourne un code d'état autre que 200 ou que ses données de réponse ne sont pas bien formées, alors cette variable est évaluée à la valeur MISS.
La valeur de cette variable n'est significative qu'après la phase de traitement de la requête access, ou BYPASS est toujours donné.
Cette variable a été introduite pour la première fois dans la version v0.14.
$srcache_store_status
type: string
cacheable: no
writable: no
Cette variable Nginx donne le statut de mise en cache actuel pour la phase "store". Deux valeurs possibles, STORE et BYPASS peuvent être obtenues.
Comme les réponses pour la sous-requête "store" sont toujours rejetées, la valeur de cette variable sera toujours STORE tant que la sous-requête "store" est effectivement émise.
La valeur de cette variable n'est significative qu'au moins lorsque les en-têtes de requête de la requête actuelle (principale) sont envoyés. Le résultat final ne peut être obtenu qu'après l'envoi de tout le corps de réponse si l'en-tête de réponse Content-Length n'est pas spécifié pour la requête principale.
Cette variable a été introduite pour la première fois dans la version v0.14.
Problèmes connus
- Sur certains systèmes, activer aio et/ou sendfile peut empêcher srcache_store de fonctionner. Vous pouvez les désactiver dans les emplacements configurés par srcache_store.
- La directive srcache_store ne peut pas être utilisée pour capturer les réponses générées par les directives de sous-requête de echo-nginx-module comme echo_subrequest_async et echo_location. Il est recommandé d'utiliser HttpLuaModule pour initier et capturer des sous-requêtes, ce qui devrait fonctionner avec srcache_store.
Précautions
- Il est recommandé de désactiver la compression gzip de votre serveur backend et d'utiliser le ngx_http_gzip_module de nginx pour faire le travail. Dans le cas de ngx_http_proxy_module, vous pouvez utiliser le paramètre de configuration suivant pour désactiver la compression gzip du backend :
proxy_set_header Accept-Encoding ""; - Ne pas utiliser la directive if du ngx_http_rewrite_module dans le même emplacement que celui de ce module, car "if est maléfique". Au lieu de cela, utilisez ngx_http_map_module ou lua-nginx-module combiné avec les directives srcache_store_skip et/ou srcache_fetch_skip de ce module. Par exemple :
map $request_method $skip_fetch { default 0; POST 1; PUT 1; } server { listen 8080; location /api/ { set $key "$uri?$args"; srcache_fetch GET /memc $key; srcache_store PUT /memc $key; srcache_methods GET PUT POST; srcache_fetch_skip $skip_fetch; # proxy_pass/drizzle_pass/content_by_lua/echo/... } }
Dépannage
Pour déboguer des problèmes, vous devez toujours vérifier d'abord votre fichier error.log de Nginx. Si aucun message d'erreur n'est imprimé, vous devez activer les journaux de débogage de Nginx pour obtenir plus de détails, comme expliqué dans debugging log.
Plusieurs pièges courants pour les débutants :
- La réponse d'origine porte un en-tête
Cache-Controlqui désactive explicitement la mise en cache et vous ne configurez pas de directives comme srcache_response_cache_control. - La réponse d'origine est déjà compressée en gzip, ce qui n'est pas mis en cache par défaut (voir srcache_ignore_content_encoding).
- Memcached pourrait retourner
CLIENT_ERROR bad command line formatlors de l'utilisation d'une clé trop longue (250 caractères à partir de la version 1.4.25). Il est donc plus sûr d'utiliserset_md5 $key $uri$args;au lieu deset $key $uri$args;. La directiveset_md5(et plus) est disponible à partir du module set-misc d'OpenResty. - Nginx pourrait retourner
client intended to send too large bodylors de la tentative de stockage d'objets plus grands que 1 Mo dans le backend de stockage, auquel casclient_max_body_sizede nginx doit être défini sur une valeur plus élevée. - Memcached pourrait échouer à stocker des objets plus grands que 1 Mo, provoquant des erreurs comme
srcache_store subrequest failed status=502. Depuis la version 1.4.2, Memcached prend en charge une option de ligne de commande-Ipour remplacer la taille par défaut de chaque page de slab. Veuillez lire sa page de manuel pour plus d'informations.
Suite de tests
Ce module est livré avec une suite de tests pilotée par Perl. Les cas de test sont également déclaratifs. Merci au module Test::Nginx dans le monde Perl.
Pour l'exécuter de votre côté :
$ PATH=/path/to/your/nginx-with-srcache-module:$PATH prove -r t
Comme un seul serveur nginx (par défaut, localhost:1984) est utilisé dans tous les scripts de test (.t fichiers), il est sans signification d'exécuter la suite de tests en parallèle en spécifiant -jN lors de l'invocation de l'utilitaire prove.
Certaines parties de la suite de tests nécessitent également que les modules ngx_http_rewrite_module, echo-nginx-module, rds-json-nginx-module, et drizzle-nginx-module soient activés lors de la construction de Nginx.
Voir aussi
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-srcache.