Nginx не кеширует данные


15

У меня есть REST API за прокси-сервером nginx. Прокси работает нормально, но я не могу кешировать ответы. Любая помощь приветствуется:

Конфигурация 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;
        }
    }
}

Независимо от того, что я пробовал, Proxy-Cache всегда возвращается как MISS:

Заголовки запроса:

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

Заголовки ответов:

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

Я подозреваю, что это что-то с заголовками клиента, но даже если я произвожу вызов через curl и проверю заголовки, ответа не будет.

заранее спасибо


1
В заголовке запроса: Cache-Control:max-age=0... это подразумевает "не кэшировать этот запрос".
Натан C

Есть ли способ для меня, чтобы игнорировать это в заголовке клиента? Это не объясняет, почему он не работает через curl, хотя ....
user2630270

@ user2630270 Каков первоначальный URL-адрес и метод запроса? Каков промежуточный ответ?
Ксавье Лукас,

@XavierLucas - методы для приведенных выше заголовков - GET, так как сейчас я решаю проблему Chrome. Запрос выглядит примерно так: nginxserver: port / solr / asd / select? Q = *: *. Я не знаю, как получить промежуточный ответ. Где я могу найти инструкции по этому вопросу?
user2630270

Если я запускаю приложение напрямую, не проходя nginx, с тем же запросом я получаю следующие заголовки ответа: Content-Type: text / plain; charset = UTF-8 Transfer-Encoding: chunked
user2630270

Ответы:


44

Вы не указали nginx, сколько времени ответ действителен и должен быть отправлен из кэша.

Это должно быть указано в proxy_cache_validдирективе.

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

Но это не будет работать для запросов POST, потому что у вас нет ключа кеша, который отличается от запроса POST к другому по тому же URL, если у них нет одинакового содержимого.

Так что вам нужно будет настроить ключ кеша на $host$request_uri|$request_body. Вам придется следить за размером кеша ( proxy_cache_pathпараметром max_size) и прокси-буфером ответов, proxy_buffer_sizeчтобы он соответствовал вашим потребностям.


Хорошо, спасибо, парень! Это сработало. Хотелось бы, чтобы это было задокументировано где-то более явно.
user2630270

Если эта директива не установлена, то любой ответ будет кэширован. Но тот переопределяется заголовком X-Accel-Expire, Cache-Control или Expire приложения. По крайней мере, Set-Cookie и Vary могли бы избежать кеша. Эти факты раскрыты в док. Я создал простой скрипт для тестирования, потому что мой фреймворк, Laravel, всегда отправляет вышеуказанные заголовки.
Виктор Агилар

16

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

Синтаксис: proxy_cache_valid [код ...] время;

...

Параметры кэширования также могут быть установлены непосредственно в заголовке ответа. Это имеет более высокий приоритет, чем установка времени кэширования с помощью директивы.

  • Поле заголовка «X-Accel-Expires» устанавливает время кэширования ответа в секундах. Нулевое значение отключает кэширование для ответа. Если значение начинается с префикса @, оно устанавливает абсолютное время в секундах с начала эпохи, до которого ответ может кэшироваться.
  • Если заголовок не включает поле «X-Accel-Expires», параметры кэширования могут быть установлены в полях заголовка «Expires» или
    «Cache-Control».
  • Если заголовок содержит поле «Set-Cookie» , такой ответ не будет кэширован.
  • Если заголовок содержит поле «Vary» со специальным значением «*», такой ответ не будет кэширован (1.7.7). Если заголовок содержит
    поле «Vary» с другим значением, такой ответ будет кэшироваться
    с учетом соответствующих полей заголовка запроса (1.7.7).

Обработка одного или нескольких из этих полей заголовка ответа может быть отключена с помощью директивы proxy_ignore_headers .

Большинство веб-приложений устанавливают Set-Cookieзаголовок, поэтому ответ не будет кэшироваться. Чтобы исправить это, используйте эту директиву:

proxy_ignore_headers Set-Cookie;
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.