
我正在嘗試將 Nginx 配置為快取反向代理。來源伺服器是 Apache,它託管一個 WordPress 實例(如果重要的話)。
反向代理功能按預期工作,但快取似乎不起作用。如果我連續兩次獲得相同的靜態資源,我就會獲得x-proxy-cache: MISS
兩次。
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 代理的第二個請求應該會導致 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
上面相同的命令,但使用頁面而不是圖像,會產生相同的結果,但總是失敗。
為什麼Nginx拒絕快取資源?
答案1
你應該設定 proxy_buffering on
,否則 nginx 將不會快取回應!
官方文件說:
當緩衝被停用時,回應將在收到後立即同步傳遞到客戶端。 nginx nginxwill not try to read the whole response from the proxied server.
一次可以從伺服器接收的資料的最大大小由 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
,就沒有問題了。