对Nginx中的缓存设置的深入理解

一、背景

网站已经运行有一段时间了,起初采用了nginx的反向代理,在location中设置了expires 30d,当时没有去仔细想如何合适的设计缓存。后来,我美化了网站的一些界面,修改了一些静态文件,更新到云服务器上,再次访问的时候发现,我所修改的静态文件资源并没有发生变化,仍是之前的那些…

设置缓存的好处无非就是在前端和后端之间建立额外的数据副本,用于减小请求后端服务器的压力,减轻了网路的压力,同时也减少了网络中数据传输的延迟性也便提高用户访问网站的速度。甚至在有时候,后台某台服务器崩了,如果还有缓存存在,则确保了网站短时间的稳定性,方便及时维护。

因此做此笔记,以便再次深入学习nginx如何设置合理的缓存和删除缓存。


二、原因分析

经过google浏览了一些好的博客,学习到了nginx的缓存机制其实有三种,而我之前所使用的expires 30d,其实使用了nginx缓存机制中的基于web的缓存技术,其基本思想利用了客户端访问的时间局部性原理,也就是当客户端访问一次服务器后,将响应的数据生成一份缓存,保存在本地客户端,这样,下次在访问服务器的时候,会首先访问本地浏览器的缓存,如果本地缓存没有过期,则直接从缓存中拿取数据,否则的话,再去访问服务器,生成本地的缓存副本。

如下图,是访问我的网站中某个js资源的相应头中的信息(我只设置了expires):

{width=80%}

说明:

1.Cache-Control:表示缓存持续的时间,以服务器时间为基准。

2.Expires:表示缓存过期时间。

3.Last-Modified:表示上次缓存过期后,新生成的本地浏览器的副本的日期。

注:
因为我才用的这种方式是基于本地浏览器的缓存,因此想要删除缓存只有通过删除本地浏览器的历史缓存才行,这种方式带来的弊端是,更新缓存的主动权在客户端,而非服务器端,因此基本上要想更新所有用户的历史缓存是很麻烦的。


三、另外两种基于Nginx服务器端的缓存

另外还有其他两种缓存机制,这里也简单的介绍下。


(1)404驱动缓存

从名字来看,可以大致了解到该缓存基于404找不到资源来进行缓存驱动的,使用了Nginx自身的proxy store对404错误进行转发到内部请求处理服务器,进行响应,然后将缓存保存在服务器中缓存文件里。

其主要的响应和设置缓存的步骤如下:

1.首先,nginx接受客户端的请求,比如客户端要请求某个css或者js或者图片等资源。

2.nginx会先在自己的缓存中查找是否有相应的数据资源,如果有则直接返回给客户端;如果没有,则抛出404资源找不到的异常。然后服务器捕捉到后,向内部服务器发送请求,然后内部服务器处理请求,最后nginx将响应的数据发送给前端,同时在服务器的本地保存缓存的副本。


(2)资源不存在驱动web缓存

该方法和404驱动缓存不同的是该缓存机制是需要if判断是否存在资源,而进一步进行重定向。


四、缓存的配置

它可以配置在http,server或者location中,基本的配置参数如下:

首先要在相应的地方创建存放缓存文件的文件夹,我这里是/usr/local/nginx/cache,这个一定要提前设置,否则启动nginx会报错!


在最顶层http中进行配置

1
2
3
4

proxy_cache_path /usr/local/nginx/cache levels=1:2 keys_zone=cache_one:100m inactive=1d max_size=10g;
#设置缓存存放的文件路径,levels是可选的,表示目录层级,表示两级子目录,keys_zone表示缓存共享内存区的名称和共享内存区的总的大小,用于多个进程或线程共享访问。keys_zone:表示缓存多长时间失效,max_size表示允许存放在磁盘上缓存数据的最大值


在server中进行配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

proxy_cache_methods GET HEAD;
#设置允许缓存的http方法,默认情况下GET和HEAD请求会缓存,所以如果不是特别需要缓存POST,则可以不用设置

proxy_cache_valid 200 10m;
proxy_cache_valid 404 30s;
#可以针对不同的请求响应码设置缓存时间

proxy_cache_valid any 5m;
#如果想为所有的响应码设置相同的缓存时间,用any

proxy_cache_min_uses 2;
#设置为请求设置最少发送2次,才对其数据进行缓存



在location中要选择http中指定的内存共享区,进行缓存的存放,需添加如下指令

1
2
3
4
5

proxy_cache cache_one
# 指定路由匹配中的缓存存放的内存共享区
# proxy_cache机制开启后会检测被服务器的HTTP响应头中的"Cache-Control""Expire"头域。如,Cache-Control为no-cache时,是不会缓存数据的。
# 需要设置proxy_buffing on;

注:除了proxy_cache_path需要配置在http全局中,其他的配置可以配置在server中也可以配置在location中,只不过缓存的范围不同


五、整体配置下nginx.conf和default.conf

配置nginx.conf中的http

1
2
3
4
5
6
7
8
9
10
11
http {

##
# Basic Settings
##

# 默认请求报文的最大限量
client_max_body_size 200M;

proxy_cache_path /usr/local/nginx/cache levels=1:2 keys_zone=cache_one:30m inactive=1d max_size=5g;
...

配置default中的server和location

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
proxy_buffering on;
proxy_buffer_size 4k;
# 代理缓存的大小(通常为服务器端响应的数据)
proxy_buffers 2 8k;
# 代理缓存的总大小(响应数据报大小+请求报文段大小)
proxy_busy_buffers_size 8k;
# 请求繁忙时,设置的缓存大小,必须大于等于总buffer大小
proxy_temp_path /usr/local/nginx/temp 1 2;
# 设置缓存临时存放的文件目录
proxy_max_temp_file_size 20M;
# 缓存所有临时文件最大的空间
proxy_temp_file_write_size 8k;
# 单个临时文件的最大空间

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404;
include uwsgi_params;
# uwsgi_pass 127.0.0.1:8002;
uwsgi_pass SYZ;
proxy_cache cache_one;
#此处的cache_one必须与http中配置的缓存区域名称相同,表示该缓存存放到目标内存共享区中
proxy_cache_valid 200 304 12h;
proxy_cache_valid 301 302 1d;
proxy_cache_valid any 1m;
proxy_cache_key $uri$is_args$args;
# uwsgi_pass e_mall;
}

做完笔记,还是蛮有成就感的!