Nginx как обратный прокси-сервер не кэширует

Nginx как обратный прокси-сервер не кэширует

Я пытаюсь настроить Nginx как кэширующий обратный прокси. Исходный сервер — Apache, и на нем размещен экземпляр WordPress, если это имеет значение.

Функционал обратного прокси работает как и ожидалось, но кэш, похоже, не работает. Если я получаю один и тот же статический ресурс дважды подряд, я получаю x-proxy-cache: MISSдважды.

assodigitale.it — это домен, 138.201.87.123 — IP-адрес исходного сервера, а 138.201.87.124 — IP-адрес прокси-сервера Nginx.

Исходный сервер, похоже, отвечает, разрешая прокси-серверу кэшировать ресурс:

$ curl --connect-to ::138.201.87.123:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
date: Sun, 11 Mar 2018 20:59:39 GMT
server: Apache/2.4.25 (Debian)
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
accept-ranges: bytes
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
content-type: image/jpeg

Первый запрос к прокси-серверу, как и ожидалось, приводит к ошибке MISS:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:04:00 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

Второй запрос к прокси-серверу Nginx должен был привести к HIT, но в результате снова MISS:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:05:52 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

Вот соответствующая часть моего конфига nginx:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;

server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    location / {
        proxy_cache revproxy;
        add_header X-Proxy-Cache $upstream_cache_status;
        add_header Strict-Transport-Security "max-age=4838400; includeSubDomains; preload";

        proxy_pass  https://138.201.87.123;
        proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
        proxy_cache_bypass $http_x_forceflushcacheurl;
        proxy_cache_lock on;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_hide_header Upgrade;
        proxy_buffering off;
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;
        proxy_ignore_headers Set-Cookie;

        http2_push_preload on;
        client_max_body_size 64M;
    }
}

Каталог /srv/cache/nginxимеет права доступа 755 и www-dataвладельца, а Nginx работает как www-data. Фактически, Nginx записывает туда свои папки, а именно 0 1 2 3 4 5 6 7 8 9 a b c d e f, но общее занимаемое пространство теперь составляет 344 Кб, для сайта, который довольно большой и имеет гораздо больше, чем случайный трафик.

Попытка выполнить те же curlкоманды, но со страницами вместо изображений, дает тот же результат — всегда ПРОМАХ.

Почему Nginx отказывается кэшировать ресурсы?

решение1

необходимо установить proxy_buffering on, иначе nginx не будет кэшировать ответ!

официальныйдокументсказал:

Если буферизация отключена, ответ передается клиенту синхронно, сразу по мере получения. nginx will not try to read the whole response from the proxied server.Максимальный размер данных, которые nginx может получить от сервера за один раз, задается директивой proxy_buffer_size.

решение2

Я скопировал конфигурацию с другого похожего прокси-сервера Nginx, который я использую, адаптировал ее к сайту, и теперь она работает.

Вот конфигурация, которую я сейчас использую:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;    
server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

        ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;    
        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        keepalive_timeout    60;
        ssl_session_timeout  10m;

    location / {
            proxy_cache revproxy;
            add_header X-Proxy-Cache $upstream_cache_status;

            proxy_pass  https://138.201.87.123;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_hide_header      Upgrade;
            proxy_buffering on;
            proxy_connect_timeout       600;
            proxy_send_timeout          600;
            proxy_read_timeout          600;
            send_timeout                600;
            client_max_body_size 64M;
    }
}

Хотя это может быть ответом, поскольку решает проблему, я не понимаю, почему это работает (или, точнее, почему предыдущая конфигурация не работала), поэтому я не собираюсь принимать свой собственный ответ.

Возможно, кто-то сможет заметить особую разницу в двух конфигурациях, которая заставляет кэш работать: это был бы приемлемый ответ.

решение3

У нас была похожая проблема. Мы использовали nginx в качестве кэша прокси для контейнера s3 (чтобы мы могли поддерживать белый список IP-адресов). Мы заметили, что не получаем данные с конечной точки https, хотя наш прокси-сервер работал на https. Похоже, nginx это не понравилось. После того, как мы переключились с httpна https, никаких проблем.

Связанный контент