Nginx ne met pas les données en cache

15

J'ai une API REST derrière un proxy nginx. Le proxy fonctionne correctement, mais je ne parviens pas à mettre en cache les réponses. Toute aide serait très appréciée:

Configuration Nginx:

worker_processes  10;
error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;

pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
        proxy_cache_path /path/to/cache/dir keys_zone=one:60m;
        proxy_cache_methods GET HEAD POST;

     upstream backend {
        server server1 backup;
        server server2 weight=5;
    }
    access_log  logs/access.log;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

    server {
        listen       7076;
        server_name  localhost;
        #charset koi8-r;
        access_log  logs/host.access.log;

        location / {
            add_header 'Access-Control-Allow-Origin' *;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Headers' 'Content-Type,Accept';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';

            proxy_cache one;
            proxy_cache_key $host$uri$is_args$args;

            add_header X-Proxy-Cache $upstream_cache_status;

            proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
            proxy_ignore_headers Set-Cookie;
            proxy_ignore_headers Cache-Control;

            proxy_hide_header Cache-Control;
            proxy_hide_header Set-Cookie;
            proxy_pass http://backend;
        }
    }
}

Peu importe ce que j'ai essayé, le Proxy-Cache revient toujours en tant que MISS:

Les en-têtes de demande sont:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:nginxserver:portnumber
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36

Les en-têtes de réponse sont:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type,Accept
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Type:text/plain;charset=UTF-8
Date:Wed, 15 Oct 2014 16:30:18 GMT
Server:nginx/1.7.4
Transfer-Encoding:chunked
X-Proxy-Cache:MISS

Je soupçonne que c'est quelque chose avec les en-têtes client, mais même si j'émets l'appel via curl et vérifie les en-têtes, il n'y a pas de réponse.

Merci d'avance

user2630270
la source
1
Dans l'en-tête de la demande: Cache-Control:max-age=0... cela signifie "ne pas mettre en cache cette demande".
Nathan C
Existe-t-il un moyen pour moi d'ignorer cela dans l'en-tête client? Cela n'explique pas non plus pourquoi cela ne fonctionne pas via curl ....
user2630270
@ user2630270 Quelle est l'URL et la méthode de la demande initiale? Quelle est la réponse intermédiaire?
Xavier Lucas
@XavierLucas les méthodes pour les en-têtes ci-dessus sont GET puisque je suis en train de dépanner le problème Chrome. La demande est quelque chose dans le sens de nginxserver: port / solr / asd / select? Q = *: *. Je ne sais pas comment capturer une réponse intermédiaire. Où puis-je trouver des instructions à ce sujet?
user2630270
Si je frappe l'application directement sans passer par nginx, avec exactement la même requête, j'obtiens les en-têtes de réponse suivants: Content-Type: text / plain; charset = UTF-8 Transfer-Encoding: chunked
user2630270

Réponses:

44

Vous n'avez pas dit à nginx combien de temps la réponse est valide et doit être servie depuis le cache.

Cela doit être spécifié avec la proxy_cache_validdirective.

proxy_cache one;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 10m;

Mais cela ne fonctionnera pas pour les requêtes POST car vous n'avez pas de clé de cache qui diffère d'une requête POST à ​​une autre sur la même URL si elles n'ont pas le même contenu.

Vous devrez donc régler la clé de cache sur $host$request_uri|$request_body. Vous devrez surveiller la taille du cache ( proxy_cache_pathparamètre max_size) et le tampon de réponse du proxy proxy_buffer_sizeafin qu'il corresponde à vos besoins.

Xavier Lucas
la source
Bien, merci mec! Ça a marché. J'aimerais que cela soit documenté quelque part un peu plus explicitement.
user2630270
Si cette directive n'est pas définie, toute réponse sera mise en cache. Mais celui-ci est remplacé par l'en-tête X-Accel-Expire, Cache-Control ou Expire de l'application. Au moins, Set-Cookie et Vary pourraient éviter le cache. Ces faits sont exposés dans le doc. J'ai créé un script simple à tester car mon framework, Laravel, envoie toujours les en-têtes ci-dessus.
Victor Aguilar
16

De: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache_valid

Syntaxe: proxy_cache_valid [code ...] time;

...

Les paramètres de mise en cache peuvent également être définis directement dans l'en-tête de réponse. Cela a une priorité plus élevée que la définition du temps de mise en cache à l'aide de la directive.

  • Le champ d'en-tête «X-Accel-Expires» définit le temps de mise en cache d'une réponse en secondes. La valeur zéro désactive la mise en cache pour une réponse. Si la valeur commence par le préfixe @, elle définit un temps absolu en secondes depuis Epoch, jusqu'à lequel la réponse peut être mise en cache.
  • Si l'en-tête ne comprend pas le champ «X-Accel-Expires», les paramètres de mise en cache peuvent être définis dans les champs d'en-tête «Expires» ou
    «Cache-Control».
  • Si l'en-tête comprend le champ «Set-Cookie» , une telle réponse ne sera pas mise en cache.
  • Si l'en-tête comprend le champ "Varier" avec la valeur spéciale "*", une telle réponse ne sera pas mise en cache (1.7.7). Si l'en-tête comprend
    le champ "Varier" avec une autre valeur, une telle réponse sera mise en cache
    en tenant compte des champs d'en-tête de demande correspondants (1.7.7).

Le traitement d'un ou plusieurs de ces champs d'en-tête de réponse peut être désactivé à l'aide de la directive proxy_ignore_headers .

La plupart des applications Web définissent l'en- Set-Cookietête, donc une réponse ne sera pas mise en cache. Pour résoudre ce problème, utilisez cette directive:

proxy_ignore_headers Set-Cookie;
Hieu
la source