Назад | Перейти на главную страницу

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 отказывается кэшировать ресурсы?

вы должны установить proxy_buffering on, иначе nginx не кеширует ответ!

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

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

Я скопировал конфигурацию из другого аналогичного прокси-сервера 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;
    }
}

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

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

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