这一篇记录一下Nginx作为Web服务器缓存,减少对应用服务器请求次数 ,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!
Nginx作为Web缓存服务器,它介于客户端和应用服务器之间,当用户通过浏览器访问一个URL时,web缓存服务器会去应用服务器获取要展示给用户的内容,将内容缓存到自己的服务器上,当下一次请求到来时,如果访问的是同一个URL,web缓存服务器就会直接将之前缓存的内容返回给客户端,而不是向应用服务器再次发送请求。web缓存降低了应用服务器、数据库的负载,减少了网络延迟,提高了用户访问的响应速度,增强了用户的体验。
目录
原理
相关指令
proxy_cache_path
proxy_cache
proxy_cache_key
proxy_cache_valid
proxy_cache_min_uses
proxy_cache_methods
测试案例
环境准备
tomcat
Nginx配置
测试
清除缓存
nginx配置并测试
设置不缓存的数据
相关指令
proxy_no_cache
proxy_cache_bypass
测试
Nginx是从0.7.48版开始提供缓存功能。Nginx是基于Proxy Store来实现的,其原理是把URL及相关组合当做Key,在使用MD5算法对Key进行哈希,得到硬盘上对应的哈希目录路径,从而将缓存内容保存在该目录中。
Nginx的web缓存服务主要是使用ngx_http_proxy_module模块相关指令完成。
该指定用于设置缓存文件的存放路径。
语法 | proxy_cache_path path [levels=number] keys_zone=zone_name:zone_size [inactive=time][max_size=size]; |
---|---|
默认值 | — |
位置 | http |
path:缓存路径地址,如:/usr/local/proxy_cache。
levels: 指定该缓存空间对应的目录,最多可以设置3层,每层取值为1|2如 :
levels=1:2 缓存空间有两层目录,第一次是1个字母,第二次是2个字母,从MD5字符串倒序取值。
举例说明:
itheima[key]通过MD5加密以后的值为 43c8233266edce38c2c9af0694e2107d
levels=1:2 最终的存储路径为/usr/local/proxy_cache/d/07
levels=2:1:2 最终的存储路径为/usr/local/proxy_cache/7d/0/21
levels=2:2:2 最终的存储路径为??/usr/local/proxy_cache/7d/10/e2
keys_zone:用来为这个缓存区设置名称和指定大小。
inactive:指定缓存的数据多次时间未被访问就将被删除,如:
inactive=1d 缓存数据在1天内没有被访问就会被删除。
max_size:设置最大缓存空间,如果缓存空间存满,默认会覆盖缓存时间最长的资源。
配置实例:
http{
proxy_cache_path /usr/local/proxy_cache keys_zone=yjh:200m levels=1:2:1 inactive=1d max_size=20g;
}
该指令用来开启或关闭代理缓存,如果是开启则自定使用哪个缓存区来进行缓存。
语法 | proxy_cache zone_name|off; |
---|---|
默认值 | proxy_cache off; |
位置 | http、server、location |
zone_name:指定使用缓存区的名称。
该指令用来设置web缓存的key值,Nginx会根据key值MD5哈希存缓存。
语法 | proxy_cache_key key; |
---|---|
默认值 | proxy_cache_key $scheme$proxy_host$request_uri; |
位置 | http、server、location |
该指令用来对不同返回状态码的URL设置不同的缓存时间。
语法 | proxy_cache_valid [code ...] time; |
---|---|
默认值 | — |
位置 | http、server、location |
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
为200和302的响应URL设置10分钟缓存,为404的响应URL设置1分钟缓存
proxy_cache_valid any 1m;
对所有响应状态码的URL都设置1分钟缓存
该指令用来设置资源被访问多少次后被缓存。
语法 | proxy_cache_min_uses number; |
---|---|
默认值 | proxy_cache_min_uses 1; |
位置 | http、server、location |
该指令用户设置缓存哪些HTTP方法。
语法 | proxy_cache_methods GET|HEAD|POST; |
---|---|
默认值 | proxy_cache_methods GET HEAD; |
位置 | http、server、location |
默认缓存HTTP的GET和HEAD方法,不缓存POST方法。
如上,我在阿里服务器上有一个tomcat,端口8080,在webapps目录下新建一个js目录并放入一个js文件,还有一个Nginx,监听8090端口,我们希望在客户端发送请求获取获取应用服务器资源的时候,先经过Nginx,Nginx从应用服务器获取到资源后返回客户端,并缓存一份到配置的/usr/local/proxy_cache目录下,下次客户端再次访问同样的资源,就不必再去应用服务器获取,Nginx直接返回缓存的就可以啦。
启动tomcat,浏览器访问 http://190.118.52.56:8080/js/jquery-1.10.1.js 可以正常返回js的内容。
在http块中添加一个server块监听8090端口,并添加upstream块和proxy_cache_path
proxy_cache_path /usr/local/proxy_cache levels=2:1 keys_zone=yjh:200m inactive=1d max_size=20g;
upstream backend{
server localhost:8080;
}
server {
listen 8090;
server_name localhost;
location / {
proxy_cache yjh; # 指定使用缓存区的名称,注意要与 proxy_cacha_path中keys_zone指定的一致
proxy_cache_valid 200 5d; # 为200响应码的请求设置缓存时间为5天
proxy_pass http://backend/js/;
}
}
确保tomcat和nginx都正常启动后,浏览器访问 http://190.118.52.56:8090/jquery-1.10.1.js 可以正常返回,并且此时进入设置的缓存目录会发现里面有一个缓存好的文件。
cd /usr/local/proxy_cache
tree
为了更方便的看到配置的缓存是否生效,可以在nginx配置中追加配置 add_header nginx-cache "$upstream_cache_status"; 向浏览器响应头中添加一个参数nginx-cache来确定,值为HIT时说明命中了缓存,请求的结果来源于nginx的缓存,如果值为MISS,说明没有使用缓存的数据。
第一次访问 http://190.118.52.56:8090/jquery-1.10.1.js nginx-cache值为MISS,当再次访问的时候值就为HIT了。
实在不放心,可以把tomcat停掉,访问还是一样会返回数据。
我们可以直接将/usr/local/proxy_cache缓存目录下的文件删除,或者可以通过添加ngx_cache_purge模块来清楚缓存。
安装ngx_cache_purge模块
下载
从官网下载安装包 点此去下载 然后上传到/usr/local目录下。
解压
tar -zxf ngx_cache_purge-2.3.tar.gz
使用 nginx -V 查看nginx已有配置:
进入Nginx的安装目录,使用./configure进行参数配置,之前我已经安装过--with-http_ssl_module --with-stream,在执行configure时不要漏掉:
cd nginx-1.20.1
./configure --with-http_ssl_module --with-stream --add-module=/root/nginx/module/purge
使用make进行编译:
make
备份sbin目录下的nginx文件:
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold
将编译后的objs中的nginx拷贝到nginx的sbin目录下:
cp objs/nginx /usr/local/nginx/sbin
使用make upgrade进行升级:
make upgrade
如果执行make upgrade的时候报如下错误:
只要指定nginx配置文件的方式重新启动后再执行upgrade就可以了,如下:
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
在nginx的配置文件中追加如下配置:
location ~/purge(/.*) {
proxy_cache_purge yjh $scheme$proxy_host$request_uri; # 参数: 缓存名称 key
}
缓存名称与上面配置的一致,key上面使用的默认配置,这里保持一致也用$scheme$proxy_host$request_uri。
访问 http://190.118.52.56:8090/purge/juqery-1.10.1.js 清除缓存的js文件,结果却404,如下:
原因在于 访问 http://190.118.52.56:8090/jquery-1.10.1.js 和 访问 http://190.118.52.56:8090/purge/jquery-1.10.1.js 实际访问的是两个地址,所以后面的访问会404。我们可以通过配置日志的方式记录实际访问的地址到日志文件,实际打印的地址如下:
我们把proxy_cache_key的值以及使用到的地方不再使用默认值,比如改为yjh,完整配置如下:
proxy_cache_path /usr/local/proxy_cache levels=2:1 keys_zone=yjh:200m inactive=1d max_size=20g;
log_format myformat $scheme$proxy_host$request_uri;
upstream backend{
server localhost:8080;
}
server {
listen 8090;
server_name localhost;
location / {
access_log logs/access.log myformat;
proxy_cache yjh;
proxy_cache_key yjh;
proxy_cache_valid 200 5d;
proxy_pass http://backend/js/;
add_header nginx-cache "$upstream_cache_status";
}
location ~/purge(/.*) {
access_log logs/access.log myformat;
proxy_cache_purge yjh yjh;
}
}
重启nginx后,再次访问 http://190.118.52.56:8090/purge/jquery-1.10.1.js 就会成功的清楚nginx的web缓存,清除后再次访问 http://1190.118.52.56:8090/jquery-1.10.1.js 查看浏览器header时就会发现 nginx-cacha的值变为了MISS,说明没有使用缓存的数据。
比如说对于一些经常发生变化的数据。如果进行缓存的话,就很容易出现用户访问到的数据不是服务器真实的数据。所以对于这些资源我们在缓存的过程中就需要进行过滤,不进行缓存。
该指令是用来定义不将数据进行缓存的条件。
语法 | proxy_no_cache string ...; |
---|---|
默认值 | — |
位置 | http、server、location |
该指令是用来设置不从缓存中获取数据的条件。
语法 | proxy_cache_bypass string ...; |
---|---|
默认值 | — |
位置 | http、server、location |
上述两个指令都有一个指定的条件,这个条件可以是多个,并且多个条件中至少有一个不为空且不等于"0",则条件满足成立。只有条件成立时,配置才生效。
常用的配置参数有以下三个,参数及代表的含义如下:
$cookie_nocache
指的是当前请求的cookie中键的名称为nocache对应的值。
$arg_nocache和$arg_comment
指的是当前请求的参数中属性名为nocache和comment对应的属性值。
我在nginx配置文件中,追加 proxy_no_cache 配置,如下:
proxy_no_cache 1;
此时不管我们访问多少次 缓存目录 /usr/local/proxy_cache 中不会再有缓存数据,浏览器的nginx-cache值始终为MISS,说明设置的proxy_no_cache生效。
上面只是简单的设置了proxy_no_cache为1,把所有的请求都不进行缓存,这样肯定是不合适的,通常我们会设置多个参数,比如上面提到的$nocache $cookie_nocache $arg_nocache $arg_comment 这三个参数,另外如果相对特定资源不进行缓存,还是以这个js文件为例,想让js文件不缓存,可以单独再追加一个判断条件,如果是js文件,我们就在peoxy_no_cache参数后面追加一个不为零且不为空的值,使其生效,比如下面这样配置:
proxy_cache_path /usr/local/proxy_cache levels=2:1 keys_zone=yjh:200m inactive=1d max_size=20g;
log_format myformat $scheme$proxy_host$request_uri;
upstream backend{
server localhost:8080;
}
server {
listen 8090;
server_name localhost;
location / {
if ($request_uri ~ /.*\.js$){
set $mynocache 1;
}
access_log logs/access.log myformat;
proxy_cache yjh;
proxy_cache_key yjh;
proxy_cache_valid 200 5d;
proxy_pass http://backend/js/;
add_header nginx-cache "$upstream_cache_status";
#proxy_no_cache 1;
proxy_no_cache $cookie_nocache $arg_nocache $arg_comment $mynocache;
}
location ~/purge(/.*) {
access_log logs/access.log myformat;
proxy_cache_purge yjh yjh;
}
}
如上,我们在location块中追加了一个判断条件,使用正则表达式匹配访问路径,当访问的为js时,设置变量mynocache的值为1,并且将mynocache的值连通另外三个参数一起设置到peoxy_no_cache中,这样的好处是,既可以通过正则表达式拦截请求使特定的资源类型不进行缓存,又保持了灵活性,使我们可以通过浏览器或者后台发送请求的时候,在任意路径上通过添加nocache或comment 来设置哪些资源不时进行缓存。
清空/usr/local/proxy_cache目录下缓存的文件,我们重启nginx,多次访问 http://190.118.52.56:8090/jquery-1.10.1.js 发现/usr/local/proxy_cache目录下没有缓存的文件。
我们再试下从浏览器中追加参数的方式,多次访问 http://190.118.52.56:8090/jquery-1.10.1.js?nocache=1 发现/usr/local/proxy_cache目录下还是没有缓存的文件。说明配置不缓存生效。