nginx 的缓存和清理
背景
由于服务器的各方面配置都太低,经不起消耗,所以基本上所有动态的内容都以缓存形式展现,除了部分的交互使用动态意外。
但是每次修改了动态的内容,缓存有没过期,这样得必须手动清理缓存了。于是尝试使用 nginx
+ ngx_cache_purge
模块
如何清理缓存
目前官方的Nginx Web缓存服务只能为指定URL或状态码设置过期时间,不支持类似Squid的PURGE指令,手动清除指定缓存页面,但是,通过一个第三方的Nginx ngx_cache_purge
模块,可以清除指定URL的缓存。
ngx_cache_purge 模块的安装
检查是否安装
nginx -V #大写的V
看到如下:
nginx version: nginx/1.18.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'
安装
因为已经安装过 nginx,所以无法 ./configure
nginx -v #小写的V
查看版本
nginx version: nginx/1.18.0
在 官网 上找对对应的版本, down 下来, 解压
wget http://nginx.org/download/nginx-1.18.0.tar.gz
tar -zxvf nginx-1.18.0.tar.gz
在 这里 找到 ngx_cache_purge
的最新版本, down 下来, 解压
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
tar -zxvf ngx_cache_purge-2.3.tar.gz
备份启动文件
cp /sbin/nginx /sbin/nginx.bak
重新编译刚才下载的 nginx
把模块带进去编译
cd nginx-1.18.0 #第一步
# ./configure + nginx -V 看到的 configure arguments + '--add-module=/usr/software/ngx_cache_purge-2.3'
./configure --prefix=/etc/nginx (略) --add-module=/root/app/ngx_cache_purge-2.3 #第二步
make #第三步
是 make 编译, 不是 make install ,make install 会覆盖原来已经安装好的内容。编译必须没有错误,才能继续下一步
检查是否编译成功
./objs/nginx -V
如果编译成功,把 objs 下的 nginx 文件 拷贝到 /sbin 目录下,然后检查是否正常
/sbin/nginx -V
重启
/sbin/nginx -c /etc/nginx/nginx.conf
/sbin/nginx -s reload
检查下进程,正常会看到 多出的 2 个进程
ps -ef|grep nginx
root 9266 1 0 17:08 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
root 9267 9266 0 17:08 ? 00:00:00 nginx: worker process
root 9268 9266 0 17:08 ? 00:00:00 nginx: cache manager process #多出的
root 9269 9266 0 17:08 ? 00:00:00 nginx: cache loader process #多出的
root 9272 1261 0 17:08 pts/0 00:00:00 grep --color=auto nginx
没有的话, kill
进程,然后重启
缓存的配置
缓存位置
配置缓存位置,才可能定位清理。通过 proxy_cache_path
指定 缓存位置 修改/etc/nginx/nginx.conf
的 http
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
http {
....
proxy_cache_path /etc/nginx/cache levels=1:2 keys_zone=web_cache:10m max_size=10g;
proxy_temp_path /etc/nginx/cache; #缓存临时目录
....
}
其中
/etc/nginx/cache
为缓存位置,web_cache
为缓存名称 ,10m为缓存单位,10g 为最大单位
指定server 配置,修改 server
server {
listen 80;
proxy_cache web_cache; #就是keys_zone的值
.....
}
缓存等级
比如有一个URL是 http://chuchur.com/1.png
,那么这个图片如果被缓存那他的路径就是 /etc/nginx/cache/9/ad/e0bd86606797639426a92306b1b98ad9
,
level=1:2
就是把最后一位数9拿出来建一个目录,然后再把9前面的2位建一个目录,最后把刚才得到的这个缓存文件放到9/ad目录中。
同样的方法推理,如果配置level=1:1,那么缓存文件的路径就是/etc/nginx/cache/9/d/e0bd86606797639426a92306b1b98ad9
- MD5哈希过之后的路径是十六进制的,对于nignx来说查询速度更快;
- level=1:2会比level=1:1建立更多的目录,适合缓存海量文件,因为单个目录下的文件太多会降低IO性能; 如果带参数呢?
- 缓存会先被写入写入临时文件,所以建议proxy_cache_path和proxy_temp_path放在同一个文件系统当中,避免不通文件系统之间的磁盘IO消耗;
比如
http://chuchur.com/1.pngv=1
,那么缓存路径还是一样吗? 这个具体要看 缓存key的 配置
缓存key
Nginx默认会缓存所有get和head方法的请求结果,缓存的key默认使用请求字符串。 自定义key
proxy_cache_key $host$uri;
proxy_cache_key $host$uri$is_args$args;
第一个配置只根据不带参的$uri进行哈希,所以这时候加了参数和没加参数是一样的结果;
第二个配置就是把域名之后所有的内容(也就是$request_uri)都进行哈希。
所以生成的缓存目录不一样
缓存次数
指定请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存。
proxy_cache_min_uses 5;
缓存方法
指定哪些方法的请求被缓存
proxy_cache_methods GET HEAD POST;
缓存有效期
默认情况下,缓存内容是长期存留的,除非缓存的总量超出限制。可以指定缓存有效时间 所有内容缓存300天
proxy_cache_valid any 300d;
缓存状态码
响应状态码为200
,302
时,10分钟有效
proxy_cache_valid 200 302 10m;
缓存过滤
对于某些请求,是否可以不走缓存? proxy_cache_bypass: 该指令响应来自原始服务器而不是缓存。
proxy_cache_bypass $cookie_nocache $arg_nocache$airg_comment;
缓存的清理
关于 nginx
的更多设置请看 这篇
清理缓存配置
location ~ /clear_cache(/.*) {
#删除指定缓存区域cache_one的特定缓存文件$1$is_args$args
proxy_cache_purge web_cache $1$is_args$args;
#运行本机和10.0.217.0网段的机器访问,拒绝其它所有
allow 127.0.0.1;
allow 10.0.217.0/24;
deny all;
}
这样清理某个缓存文件的时候地址前面加上 /clear_cache
即可,如 :清理 文件 https://www.chuchur.com/js/a.js
,输入 https://www.chuchur.com/clear_cache/js/a.js
, 看到 Successful purge
表明清理成功。
可以每次修改动态内容之后,自动触发 缓存清理器操作
完整的例子
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
charset utf-8;
#注:proxy_temp_path和proxy_cache_path指定的路径因该在同一分区
proxy_temp_path /etc/nginx/proxy_temp_dir;
proxy_cache_path /etc/nginx/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=10g;
server {
listen 80;
server_name chuchur.com;
location / {
root html;
index index.html index.htm;
}
#用于清除缓存
location ~ /clear_cache(/.*) {
#设置只允许指定的IP或IP段才可以清除URL缓存。
allow 127.0.0.1;
allow 192.168.1.0/16;
deny all;
proxy_cache_purge cache_one $host$1$is_args$args;
}
location ~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_cache cache_one;
#对不同的HTTP状态码设置不同的缓存时间
proxy_cache_valid 200 304 12h;
#以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内
proxy_cache_key $host$uri$is_args$args;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://127.0.0.1:8080;
#缓存时间
expires 7d;
}
}
}
一些问题
该缓存的没缓存, 不该缓存的缓存了。
排除问题
add_header Nginx-Cache "$upstream_cache_status";
查看Headers
里的 Nginx-Cache
状态 是 Hit
还是 Miss
允许 一些头部信息:
proxy_ignore_headers Expires;
proxy_ignore_headers Cache-Control;
控制哪些缓存, 哪些不缓存:
set $nocache 0;
# 以 aaa,bbb,ccc 开头的不缓存
if ($request_uri ~ ^/(aaa|bbb|ccc)) {
set $nocache 1;
}
proxy_cache_bypass $nocache;
# cookie 里面设置了nocache,或者 参数传值里有aaa,bbb 的不缓存,满足一个即可
proxy_no_cache $cookie_nocache $arg_aaa $arg_bbb;
为什么明明设置了不缓存 Nginx-Cache
状态也是 BYPASS
, 拿到的还是缓存信息?
一般都是 get
请求 ,post
请求不会缓存数据
通过Network
=> Size
观察 ,居然是 (memory cache) ,也就是 ,浏览器直接从内存取的数据, 未从服务器获取最新数据
解决: 在 get
请求时传递随机字符串 :
var time = Date.now();
$.get("/aaa/bbb/ccc?time=" + time);
至此缓存和不缓存,已经缓存的自动更新的问题顺利解决。