1、缓存相关知识
使用缓存为了减少后端的压力,让请求集中到前端就能取到数据。缓存可以分为服务端缓存(redis等)、代理缓存(Nginx等)、浏览器缓存(浏览器自带)。本文说一下Nginx缓存。
Nginx代理缓存流程:首先客户端先去请求Nginx,第一次请求的时候,如果Nginx本地没有缓存,那么他会向服务器发起请求对应的数据数据,然后服务器返回对应的数据,Nginx本地进行缓存,然后返回给客户,这是在没有缓存的情况下。当用户再一次发起同一个url请求的时候,Nginx本地已经有了缓存数据,直接就可以返回客户端,不需要再请求服务端。
2、配置语法
定义缓存(不需要换行,每个参数之间使用空格即可)
Syntax:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time]; Default:- Context:http
开启或者关闭缓存,默认关闭。
Syntax:proxy_cache zone | off;
Default:proxy_cache off;
Context:http,server,location
指定缓存过期周期,code是状态码,当返回的状态码是200、502...时多久(time)缓存过期。
Syntax:proxy_cache_valid [code ...] time; Default:- Context:http,server,location
指定缓存的纬度,默认以协议+主机+url作为key缓存
Syntax:proxy_cache_key string;
Default:proxy_cache_key $scheme$proxy_host$request_uri;
Context:http,server,location
3、演示缓存
准备两台虚拟机151、152。151配置缓存和负载,152上启动3个端口模拟3台提供服务的Nginx。参考第014篇
在152上新建/opt/app/code1/url1.html;/opt/app/code2/url1.html;/opt/app/code3/url1.html;内容分别如下:
<html> <head> <meta charset="utf-8"> <title>server1</title> </head> <body style="background-color:yellow;"> <h1>Server 1 url 1<h1> </body> </html>
<html> <head> <meta charset="utf-8"> <title>server2</title> </head> <body style="background-color:red;"> <h1>Server 2 url 1<h1> </body> </html>
<html> <head> <meta charset="utf-8"> <title>server3</title> </head> <body style="background-color:blue;"> <h1>Server 3 url 1<h1> </body> </html>
在152的/etc/nginx/conf.d中新建server1.conf、server2.conf、server3.conf,分别指定端口和首页路径
server { listen 8001; server_name localhost; access_log /var/log/nginx/server1.access.log main; location / { root /opt/app/code1; index index.html index.htm; }
... ... }
server { listen 8002; server_name localhost; access_log /var/log/nginx/server2.access.log main; location / { root /opt/app/code2; index index.html index.htm; }
... ... }
server { listen 8003; server_name localhost; access_log /var/log/nginx/server3.access.log main; location / { root /opt/app/code3; index index.html index.htm; }
... ... }
在151的/etc/nginx/conf.d中新建cache_test.conf,用来负载和缓存。
upstream myLoad { server 192.168.7.152:8001; server 192.168.7.152:8002; server 192.168.7.152:8003; } proxy_cache_path /opt/app/cache levels=1:2 keys_zone=sl_cache:10m max_size=10g inactive=60m use_temp_path=off; server { listen 80; server_name localhost; #charset koi8-r; access_log /var/log/nginx/cache_test.conf main; resolver 8.8.8.8; location / { proxy_cache off; proxy_pass http://myLoad; proxy_cache_valid 200 304 12h; proxy_cache_valid any 10m; proxy_cache_key $host$uri$is_args$args; add_header Nginx-Cache "$upstream_cache_status"; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; include proxy_params; } ...... }
参数说明:
/opt/app/cache:缓存路径
levels=1:2:缓存文件分为两级目录
keys_zone=sl_cache:10m:缓存名称是sl_cache,大小是10M(1M约800个key)
max_size=10g:最大可以 缓存10g,超过最大值,Nginx安装默认规则删除
inactive=60m:60分钟内如果缓存文件没有被访问,就清理掉该缓存
use_temp_path=off:存放临时文件关闭
proxy_cache off:关闭缓存
proxy_cache_valid 200 304 12h:对于返回的是200或者304的状态码,缓存12小时过期
proxy_cache_valid any 10m:对于返回其他的状态码,10分钟过期
proxy_cache_key $host$uri$is_args$args:重新定义缓存的key,加上参数
add_header Nginx-Cache "$upstream_cache_status":添加一个头信息,返回给客户端是否已经命中缓存
proxy_next_upstream...:负载均衡的配置,如果后端的一台服务器出现500 502 503 或者超时、错误的时候跳过这一台去访问下一台
include proxy_params:代理参数单独写成了一个文件,路径/etc/nginx/proxy_params,内容如下:
proxy_redirect default; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_connect_timeout 30; proxy_send_timeout 60; proxy_read_timeout 60; proxy_buffer_size 32k; proxy_buffering on; proxy_buffers 4 128k; proxy_busy_buffers_size 256k; proxy_max_temp_file_size 256k;
测试,启动两个Nginx。
1)多次访问http://192.168.7.151/url1.html,发现是轮询访问,因为没有开启缓存,此时已经生成/opt/app/cache目录,里面是空的。
修改cache_test.conf中的proxy_cache off 为 proxy_cache sl_cache(定义的缓存名称),重新启动Nginx。
2)多次访问http://192.168.7.151/url1.html,不再轮询,访问同一端口的url1.html,/opt/app/cache目录中已有缓存文件。缓存生效。
4、如何清理指定缓存
方式一:rm -rf 缓存目录(这样所有的缓存都会清空掉)
方式二:第三方扩展模块 ngx_cache_purge
5、如何让部分页面不缓存
Syntax:proxy_no_cache string ...; Default:- Context:http,server,location
演示:在152上新建/opt/app/code1/url2.html;/opt/app/code2/url2.html;/opt/app/code3/url2.html;内容分别如下:
<html> <head> <meta charset="utf-8"> <title>server1</title> </head> <body style="background-color:yellow;"> <h1>Server 1 url 2 <h1> </body> </html>
<html> <head> <meta charset="utf-8"> <title>server2</title> </head> <body style="background-color:red;"> <h1>Server 2 url 2<h1> </body> </html>
<html> <head> <meta charset="utf-8"> <title>server3</title> </head> <body style="background-color:blue;"> <h1>Server 3 url 2<h1> </body> </html>
修改151上的配置文件cache_test.conf,在server中做如下修改,红色为新增部分。
server { listen 80; server_name localhost; #charset koi8-r; access_log /var/log/nginx/cache_test.conf main; resolver 8.8.8.8; if ($request_uri ~ ^/(url2|login|register|password/reset)){ set $cookie_nocache 1; } location / { proxy_cache sl_cache; proxy_pass http://myLoad; proxy_cache_valid 200 304 12h; proxy_cache_valid any 10m; proxy_cache_key $host$uri$is_args$args; proxy_no_cache $cookie_nocache $arg_nocache $arg_comment; proxy_no_cache $http_pragma $http_authorization; add_header Nginx-Cache "$upstream_cache_status"; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; include proxy_params; } ... ... }
说明:
proxy_no_cache配置项,参数值为0或者为空时才会缓存。
if语句中当页面以url2、login、register、password开头时,设置了变量$cookie_nocache为1,并且在proxy_no_cache中引用。
演示,首先清除缓存,以免之前的配置造成影响。重新启动nginx。
1)多次刷新http://192.168.7.151/url1.html,发现总是访问固定端口的url1.html,说明url1.html被缓存了。
2)多次刷新http://192.168.7.151/url2.html,发现轮询访问url2.html,说明url2.html没有被缓存,配置起作用了。
6、大文件分片请求
早期版本的Nginx不支持大文件分片请求,1.9版本后,支持分片请求。
语法:
Syntax:slice size; Default:slice 0; Context:http,server,location
size:表示大文件分片请求的时候,要切割成多大的碎片。
分片请求就是,浏览器首次请求后端,获取到文件的大小,根据文件大小和已经定义的size进行分割成小的请求,去请求后端。前端是一个个的小的缓存文件。如果不做大文件分片请求,如果请求断了,就要从零开始,重新请求。如果使用分片请求这个模块,每个子请求收到的数据都会形成一个独立文件,一个请求断掉了,其他请求不受影响。基于原有的请求再次请求就可以了。分片请求也有缺点,当文件很大或者slice很小的时候,会形成很多个小的请求,会与操作系统建立很多链接,产生很多文件句柄。可能会导致文件描述符耗尽等情况。