Nginx缓存配置

Nginx HTTP缓存设置

Nginx提供了 expiresetagif-modified-since 指令来实现浏览器缓存控制。

expires

如果我们使用了Nginx作为静态资源服务器,那么可以使用expires进行缓存控制。

location ~ ^/images/* {
	root /Users/xuefeihu/hugege/code-sublime;
	expires 365d;
}

当我们访问 http://moguhu.com/images/83131d36-0170-42d5-b4d5-c606674f2376.png 时,得到如下响应头。

if-modified-since

此指令用于Nginx服务器端的 Last-Modified 和浏览器的 if-modified-since 比较默认 'if_modified_since exact' 表示精确匹配,也可以使用 'if_modified_since _before' 表示只要文件的最后修改时间早于或等于浏览器端的if-modified-since时间,就返回304。

proxy_pass 流程

1、浏览器发起请求,首先Nginx根据URL在本地查找是否有代理层缓存。

2、Nginx没有找到本地缓存,则访问后端获取最新的文档,并放到Nginx本地缓存中,返回200状态码和最新的文档给浏览器。

3、Nginx找到本地缓存,首先验证文档是否过期(Cache-Control: max-age=5),如果过期,则访问后端获取最新的文档,并放入Nginx本地缓存中,返回200状态码和最新的文档给浏览器;如果文档没有过期,即if-modified-since与缓存文档的last-modified匹配,则返回304状态码给浏览器。

Nginx代理层缓存

HTTP模块配置

proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 512 4k;
proxy_busy_buffers_size 64k;
proxy_cache_path /export/cache/proxy_cache levels=1:2 keys_zone=cache:512m inactive=5m max_size=8g;
#proxy timeout
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 5s;

proxy_cache_path 指令的详细说明如下:
levels=1:2:表示创建两级目录结构,缓存目录的第一级是1个字符,第二级是2个字符,比如/export/cache/proxy_cache/7/3c/,如果将所有文件放在一级目录下的话,文件量很大,会导致文件访问慢。
keys_zone=cache:512m:设置存储所有缓存key和相关信息的共享内存区,1M大约能存储8000个key。
inactive=5m:inactive指定被缓存的内容多久不被访问将从缓存中移除,以保证内容的新鲜,默认为10分钟。
max_size=8g:最大缓存阀值,'cache manager'进程会监控最大缓存大小,当缓存达到该阀值时,该进程将从缓存中移除最近最少访问的内容。
use_temp_path:如果为on,则内容首先被写入临时文件(proxy_temp_path ),然后重命名到 proxy_cache_path 指定的目录;如果设置为off,则内容直接被写入到proxy_cache_path指定的目录。cache建议设置为off,则该特性是1.7.10提供的。

proxy_cache 配置

location = /cache {
    proxy_cache cache;
    proxy_cache_key $scheme$proxy_host$request_uri;
    proxy_cache_valid 200 5s;
    proxy_pass http://backend_tomcat/cache$is_args$args;
    add_header cache-status$upstream_cache_status;
}

上述的配置详解如下:

proxy_cache:指定使用哪个共享内存区存储缓存信息。

proxy_cache_key:设置缓存使用的key,默认为完整的访问URL。

proxy_cache_valid:为不同的响应状态码设置缓存时间。如果是 proxy_cache_valid 5s ,则200、301、302响应都将被缓存。

proxy_cache_valid不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下)。

1、以秒为单位的 'X-Accel-Expires' 响应头来设置响应缓存时间。

2、如果没有 'X-Accel-Expires' ,则可以根据 'Cache-Control' 、 'Expires' 来设置响应缓存时间。

3、否则,使用 proxy_cache_valid 设置缓存时间。

如果响应头包含 Cache-Control: private/no-cache/no-storeSet-Cookie或者只有一个 Vary: *,则响应内容将不会被缓存。可以使用 proxy_ignore_headers 来忽略这些响应头。

add_header cache-status $upstream_cache_status 在响应头中添加缓存命中的状态。

HIT:缓存命中,直接返回缓存中内容,不回源到后端。

MISS:缓存未命中,回源到后端获取最新的内容。

EXPIRED:缓存命中但过期了,回源到后端获取最新的内容。

UPDATING:缓存已过期但正在被别的Nginx Worker进程更新,配置了proxy_cache_use_stale updating指令时会存在该状态。

STALE:缓存已过期,但因后端服务出现了问题(比如后端服务挂了)返回过期的响应,配置了如proxy_cache_use_stale error timeout指令后会出现该状态。

REVALIDATED:启用proxy_cache_revalidate指令后,当缓存内容过期时,Nginx通过一次if-modified-since的请求头去验证缓存内容是否过期,此时会返回该状态。

BYPASS:proxy_cache_bypass指令有效时,强制回源到后端获取内容,即使已经缓存了。

proxy_cache_min_uses:用于控制请求多少次后响应才被缓存。默认 'proxy_cache_min_uses 1; ',如果缓存热点比较集中、存储有限,则可以通过修改该参数来来减少缓存数量和写磁盘次数。

proxy_no_cache:用于控制什么情况下响应不被缓存。比如配置 'proxy_no_cache $args_nocache' ,如果带的nocache参数值至少有一个不为空或者为0,则响应将不被缓存。

proxy_cache_bypass:类似于proxy_no_cache,它控制什么情况不使用缓存的内容,并且是直接到后端获取最新的内容。如果命中,则$upstream_cache_status为BYPASS。

proxy_cache_use_stale:当对缓存内容的过期时间不敏感,或者后端服务出问题时,即使缓存的内容不新鲜也总比返回错误给用户强(类似于托底),此时可以配置该参数,如 'proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504' ,即:如果出现超时、后端连接出错、500、502、503等错误时,即使缓存内容已过期也先返回给用户,此时$upstream_cache_status为STALE。还有一个updating表示缓存已过期但正在被别的Nginx Worker进程更新,但先返回了过期内容,此时 $upstream_cache_status 为UPDATING。

proxy_cache_revalidate:当缓存过期后,如果开启了proxy_cache_revalidate,则会发出一次if-modified-since或if-none-match条件请求,如果后端返回304,则此时$upstream_cache_status为REVALIDATED,我们将得到两个好处,节省带宽和减少写磁盘的次数。

proxy_cache_lock:当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off),则只有一个请求被发送至后端。其他请求将等待该请求的返回。当第一个请求返回后,其他相同请求将从缓存中获取内容返回。当第一个请求超过了proxy_cache_lock_timeout超时时间(默认为5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存(在1.7.8版本之前是被缓存的)。启用 proxy_cache_lock 可以应对 Dog-pile effect(缓存失效风暴)。

proxy_cache_lock_age:是1.7.8新添加的,如果在proxy_cache_lock_age指定的时间内(默认为5s),最后一个发送到后端进行新缓存构建的请求还没有完成,则下一个请求将被发送到后端来构建缓存(因为1.7.8版本之后,proxy_cache_lock_timeout超时之后返回的内容是不缓存的,需要下一次请求来构建响应缓存)。

小节

只缓存200状态码的响应,如系统错误跳转至302,此时缓存302就不对了。

有些页面不需要强一致性,可以进行几秒的缓存。比如商品详情页的库存。

静态资源文件(JS/CSS/IMAGE)可以缓存较长时间,如1个月、1年等。

参考:《亿级流量网站架构核心技术》

代码段 小部件