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很小的时候,会形成很多个小的请求,会与操作系统建立很多链接,产生很多文件句柄。可能会导致文件描述符耗尽等情况。