我将描述使Nginx永久(或至少一年)缓存图像所需要做的一切。
在开始之前,您应该了解一件事:我在此处指出的所有内容均已记录在Nginx的官方缓存指南中,但是我很懒,没有读过它,我希望我能为您节省一些你宝贵的时间。
如果您已经在生产中运行Nginx并拥有一定流量,您可能会根据处理请求所需的时间来猜测响应是来自上游服务器而不是来自Nginx缓存的,如果它很慢,那么我们知道作为一个MISS
; 另一方面,如果Nginx在缓存中找到响应并进行响应,则为HIT
。
为了避免任何猜测,最好让Nginx告诉您何时命中或未命中缓存请求,我们通过为HTTP标头提供缓存状态的状态来做到这一点。您可以选择任何想要的名称,X-Cache-Status
就像官方指南建议的那样,我喜欢:
location / {
# . . .
add_header X-Cache-Status $upstream_cache_status;
# . . .
}
现在,我们可以向服务器发出请求,并查看每个特定请求的缓存实际发生了什么:
$ curl -v localhost:8080
. . .
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Date: Fri, 20 Dec 2018 00:46:43 GMT
< Content-Type: image/png
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: public, max-age=31536000
< X-Cache-Status: HIT
继续阅读指南的第一个片段:
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_cache my_cache;
proxy_pass http://my_upstream;
}
}
根据您的设置,此配置可能会或可能不会起作用,请考虑以下几点:
标头中的Cookie
如果NginxSet-Cookie
在上游响应中看到标头,则不会缓存。
我没有这个问题,但是如果您要确保MISS
它不是关于cookie的,则可以简单地忽略所有cookie:
location / {
# . . .
proxy_ignore_headers "Set-Cookie";
# . . .
}
缓存控制标头
如果Nginx看到Cache-Control
带有Private
,No-Cache
或的标题No-Store
,则不会缓存。
我也没有这个问题,但是如果您要确保它与上游响应中的Cache-Control泄漏无关,还可以通过来忽略此标头proxy_ignore_headers
,例如,官方指南中的以下配置将忽略来自上游并强制将任何状态码(不只是200 OK
)进行高速缓存30分钟(继续读取):
location / {
proxy_ignore_headers Cache-Control;
proxy_cache_valid any 30m;
}
这听起来似乎不是一个好主意,相反,您可能希望只缓存这样的响应200 OK
:
location / {
proxy_ignore_headers Cache-Control;
proxy_cache_valid 200 30m;
}
如果您愿意,也可以忽略Expires
标头:
proxy_ignore_headers Cache-Control Expires;
代理缓冲
如果Nginx有proxy_buffering: off
,它将不会缓存。
这是on
在默认情况下,所以我不知道为什么它会是off
,但以防万一:
proxy_buffering on;
这很好地解释了为什么应该这样做on
以及为什么会影响缓存。
调整Nginx以缓存更长的时间
此时,此Nginx配置将资源缓存了30分钟,但是我们如何使它缓存更长的时间呢?
我的第一步是改成proxy_cache_valid any 30m;
说1y
:
proxy_cache_valid any 1y;
好的,重新加载Nginx后,我在30分钟后发出了一个新请求:
$ curl -v localhost:8080
. . .
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Content-Type: image/png
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: public, max-age=31536000
< X-Cache-Status: HIT
所以X-Cache-Status: HIT
,那很好。
1小时后怎么样?
$ curl -v localhost:8080
. . .
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.7
< Content-Type: image/png
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: public, max-age=31536000
< X-Cache-Status: MISS
我们得到的X-Cache-Status: MISS
显然不是我们想要的,它应该是一个HIT
。
结果proxy_cache_valid
指示Nginx,如果资源没有首先变为非活动状态,则可以缓存1y
该资源。当您请求具有更长到期时间但由于缺少请求而变得不活动的资源时,它将导致高速缓存未命中。
proxy_cache_path
在http
级别指定多久的项目可以保留在缓存中没有被访问过,所以为了缓存资源为1年的配置应该是:
proxy_cache_path . . .
inactive=1y
. . . ;
server {
location / {
# . . .
proxy_cache_valid 200 1y;
# . . .
}
}
结论
proxy_cache_path
应该inactive
比请求的到期时间(proxy_cache_valid
)更长的时间。
via https://bithavoc.io/blog/2018/12/20/caching-upstream-forever-with-nginx/
最后更新于 2022年6月26日