リバースプロキシとしてのNginxはキャッシュしない

リバースプロキシとしてのNginxはキャッシュしない

Nginx をキャッシュ リバース プロキシとして設定しようとしています。元のサーバーは Apache で、WordPress インスタンスをホストしています。

リバース プロキシ機能は期待どおりに動作していますが、キャッシュは動作していないようです。同じ静的リソースを 2 回続けて取得すると、x-proxy-cache: MISS2 回取得されます。

assodigitale.it はドメイン、138.201.87.123 はオリジン サーバーの IP アドレス、138.201.87.124 は Nginx プロキシの IP アドレスです。

オリジン サーバーは、プロキシがリソースをキャッシュすることを許可する応答をしているようです。

$ 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 プロキシへの 2 番目のリクエストは 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が、占有される全体のスペースは 344Kb になります。これは、かなり大きく、通常のトラフィックよりもはるかに多いサイトの場合です。

上記と同じcurlコマンドを、画像ではなくページで試しても、同じ結果になり、常に MISS になります。

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 プロキシから設定をコピーし、それを Web サイトに適合させたところ、動作するようになりました。

現在使用している構成は次のとおりです。

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;
    }
}

これは問題を解決するので答えにはなるかもしれませんが、なぜそれが機能するのか(より正確には、以前の構成ではなぜ機能しなかったのか)がわかりません。そのため、自分の答えを受け入れるつもりはありません。

おそらく、キャッシュを機能させる 2 つの構成の特定の違いに気付く人がいれば、それが受け入れられる回答になるでしょう。

答え3

同様の問題がありました。 s3 バケットのプロキシ キャッシュとして nginx を使用していました (IP ホワイトリストをサポートできるようにするため)。プロキシが https でサービスを提供しているにもかかわらず、https エンドポイントからソースを取得していないことに気付きました。 nginx がそれを好まなかったようです。 から に切り替えるとhttphttps問題はなくなりました。

関連情報