Nginx 作为Web服务器或者负载均衡器,一般不执行业务逻辑,而是将请求转到后端服务器,比如 Tomcat 或者 php-fpm,后端处理完毕之后将经过 nginx 将数据返回给用户。在请求转发的过程中,nginx 可将中间数据在本地进行缓存,这样未来一段时间内的请求相同的数据,Nginx 可以直接返回本地复本,而不是再次向后端服务发起请求,可以大大降低后端服务器的压力。同时,在后端服务器宕机时,Nginx 还可返回缓存数据,而不中端服务,提高了服务的可用性。
Nginx 可以将缓存数据持久化到本地磁盘上,不会因为Nginx 退出或者服务器重启而都是,Nginx 重启之后会自动扫描磁盘的上缓存数据并建立索引,保证服务的持续性。
Nginx 的缓存配置:
# 定义缓存路径、过期时间、空间大小等
proxy_cache_path /tmp/nginx/cache levels=2:2:2 use_temp_path=off keys_zone=my_cache_name:10m inactive=1h max_size=1g;
server {
listen 8000;
server_name localhost;
# 添加缓存的 http 状态头
add_header X-Cache-Status $upstream_cache_status;
location / {
# 定义缓存名称
proxy_cache my_cache_name;
# 定义缓存key
proxy_cache_key $host$uri$is_args$args;
# 针对返回装装他码单独定义缓存时间
proxy_cache_valid 200 304 10m;
# url 上代用 nocache 获取请求投中代用 nocache,切值为true 时不走缓存。
proxy_cache_bypass $arg_nocache $http_nocahe;
proxy_pass http://localhost:8080;
}
}
proxy_cache_path 的常用指令介绍:
- levels=2:2:2,表示缓存目录的层级,2:2:2 表示创建两级目录,第一个目录名用一个字符表示,第二级目录用两个字符表示,如:/tmp/nginx/cache/83/64/d4…。这样可以缓解缓存文件过多,都集中在一个目录下的检索速度慢问题。目前,nginx 最多支持三级目录(用两个冒号分割),每级1~2个字符的目录名。
- keys_zone=my_cache_name:10m,设置缓存名称,key的存储空间大小,由于Nginx 是多进程的工作模式,所以key缓存在共享内存中。按照官方文档的说法,1M的内存空间大概能存8000个key。
- use_temp_pat=off,默认为on,建议甚至为off,默认情况下,缓存内容先写到临时文件中(proxy_temp_path),然后通过重命名到 proxy_cache_path 设置的路径中。如果为 off,则缓存内容直接写入 proxy_cache_path 制定的路径中。
- inactive=1h,设置缓存的失效时间,1h表示一个小时。如果缓存数据在 inactive 给定的时间内访问过,则会被移除。
- max_size=1g,设置缓存的存储空间占用的上限,当存满时nginx 的 “cache manager”进程就会按照LRU(最近最少使用)原则清理缓存。
- manager_files, manager_threshold, manager_sleep 控制 cache manager 进程的活动周期。manager_files 设置每次 cache manager 的清除数量(默认100条),manager_threshold 控制每个清理周期的时长(默认200毫秒),manager_sleep 控制两次清理周期的时间间隔(默认50毫秒)。
- loader_files,loader_sleep,loader_threshold,用来控制“cache loader”进程的活动,“cache loader” 进程负责将之前存储在文件系统的中的缓存加载在缓存区,重启nginx的时候,这个功能比较有用,加载过程也是周期性迭代进行,loader_files设置每次加载多少条(默认100个),loader_threshold设置设置每次加载周期的时长(默认200毫秒),loader_sleep设置加载周期的间隔(默认50毫秒)。
常用缓存配置指令:
- proxy_cache : 设置使用哪个缓存区,如 proxy_cache <my_cache_name>,同一个缓存区可以被多处配置共享,默认是关闭状态,off 表示关闭缓存功能。
- proxy_cache_key:设置缓存key的格式,默认格式为 $scheme$proxy_host$request_uri,既 URL 路径,支持变量参数,使用时可以根据具体需求进行设置,比如加入 cookie 信息。
- proxy_cache_valid ,设置缓存时间,还可以根据状态码分别分别设置 缓存时间,例如:
- proxy_cache_valid 200 302 10m;
- proxy_cache_valid 301 1h;
- proxy_cache_valid any 1m;
- proxy_no_cache:用来设置不被缓存的条件,比如,proxy_no_cache$arg_nocache; 表示 url 带有参数nocahe 且指部位空或者0,则请求内容就不会被缓存,比如,curl http://127.0.0.1:8000/ 会被缓存, curl http://127.0.0.1:8000/?nocahe=1,则不会被缓存,http://127.0.0.1:8000/?nocahe=0 或者 http://127.0.0.1:8000/?nocahe= 则会被缓存。另外,还可以通过 http请求头,cookie 中的参数来控制,该指令在进行调试的时候很有用。
- proxy_cache_bypass:该指令设置在什么情况下直接从后端的获取内容,不走缓存。如果命中条件,如 proxy_cache_bypass$arg_nocache,当url带有参数nocache时(参数值为1或者非空),则直接从后端读取内容且 $upstream_cache_status 的状态值为 BYPASS。改指令和proxy_no_cache 在使用现象上类似,对用同样的设置,差别在于proxy_no_cache命中条件不缓存内容,而proxy_cache_bypass会缓存内容,比如同样是 nocache=1,对于一个尚未被缓存的url内容,proxy_no_cache 命中条件后不缓存内容,proxy_cache_bypass会缓存内容,可以关键 /tmp/nginx/cache(proxy_cache_path中设置的缓存文件路径)目录中文件的变化来感觉他们之间的差别,实际项目中,两个指令旺旺同时使用。
- proxy_cache_min_uses:在给定请求次数之后在进行缓存,默认为1(既一次请求就缓存),当缓存空间有限时,每次请求都缓存会造成比较大空间的浪费,通过这个参数可以有效区别热点数据。
- proxy_cache_use_stale:如果后端服务器出错不能返回有效结果时,返回缓存数据(即使已过期)也没有数据要好,proxy_cache_use_stale 可以用户兜底方案,作为页面容灾使用。比如可以这样设置,
proxy_cache_use_stale error timeout http_500 http__502 http_503 http_504
当后端服务器出现50x错误,或者超时或者无法链接时,则返回已过期的缓存数据,同时 $upstream_cache_status 状态值变为 STALE。另外,还可以通过 Cache-Control HTTP 头中的stale-while-revalidate 和 stale-if-error 两个扩展参数进行控制,但优先级更低。
- proxy_cache_revalidate:
- proxy_cache_methods:
- proxy_cache_lock:
- add_header Cache-Status $upstream_cache_status :在HTTP 响应头中添加缓存状态,例如,可以通过“curl http://127.0.0.1:8000/ -I”进行查看。$upstream_cache_status包含如下几种状态,比较常见的是 HIT,MISS 两种状态:
- HIT:命中缓存,直接返回缓存内容。
- MISS: 未命中缓存,将请求发给后端,同时将返回内容进行缓存。
- EXPIRED:命中缓存,但缓存数据已过期,将请求转发给后端,同时将返回内容进行缓存。
- UPDATING:当缓存已经过正在被其他nginx worker进程更新时,返回该状态吗。
- BYPASS: 当命中 proxy_cache_bypass 中设置的条件时,直接从后端源站返回内容,该变量状态变为BYPASS。
- REVALIDATED:
- STALE: 命中 proxy_cache_use_stale 指令设置的条件时,既后端服务器出现错误时,返回过期的缓存数据时,会返回这个状态码。
运维虐我千万遍,我对运维如初恋。