什么是缓存?
缓存的基本概述
缓存的基本思想是利用客户端访问的时间局限性,将客户端访问过的内容做一个副本,在一定时间内存放到本地,当改数据下次被访问时,不必连接到后端服务器反复去查询数据,而是由本地保存的副本响应数据。
保存在本地的这些副本具有一个过期时间,超过该时间将会更新。判断一个副本数据是否为过期数据的办法有很多,可以使用保留时间来判断,也可以使用数据完整度来判断。
许多web服务器还具有校验功能,就是当某些副本数据过期以后,先向后端服务器发送校验请求,后端服务器对这些数据进行校验,如果发现原数据和副本没有差别,则将过期副本重新置为可用副本。
缓存的好处
- 减轻服务器负载
- 提供网页响应效率
- 降低网络阻塞,增强网络可扩展性
为什么使用缓存?
- 服务器处理能力以及负载能力出现瓶颈,响应效率大大降低
- 为了减少网络传输延迟,提升响应效率
- 能够避免因为后端服务器出现异常以及网络故障,客户端请求数据副本能够及时响应
nginx的缓存机制
proxy模块指令
配置块 | 名称 | 名称 |
---|---|---|
http | proxy_cache_path | 指定缓冲区的路径 |
levels | 缓存目录级最高三层,每层1-2个字符表示,比如:1:1:2 三层 | |
keys_zone | 缓存块名称及内存块大小,比如:cache_item:500m表示声明一个名为cache_item大小为500m,超出大小后最早的被清除 | |
max_size | 缓存区硬盘的最大值,超出闲置数据将被清除 | |
inactive | 最长闲置时间,比如:10d ,表示一个数据被闲置10天则将被清除 | |
location | proxy_cache | 指定缓冲区,对应keys_zone中的设定的值 |
proxy_cache_key | 通过参数拼装参数key如: h o s t host hosturi i s a r g s is_args isargsargs 则会已全部md5值作为key | |
proxy_cache_valid | 对不同的状态码设置缓存有效期 |
以上nginx配置结合使用:
http {
.
.
.
proxy_cache_path /cache/nginx levels=1:2 keys_zone=imooc_cache:10m max_size=5g inactive=60m use_temp_path=off;
.
.
.
server {
.
.
.
location /api/ {
proxy_cache imooc_cache;
proxy_pass http://www.blogs-s.com:8080/api/;
proxy_cache_valid 200 304 12h;
proxy_cache_valid any 10m;
proxy_cache_key $host$uri$is_args$args;
include proxy_params;
}
}
}
proxy_params文件的配置如下:
proxy_set_header host $http_host;
proxy_set_header x-real-ip $remote_addr;
proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
proxy_connect_timeout 30;
proxy_send_timeout 60;
proxy_read_timeout 60;
proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;
访问一次页面,并向 http://www.blogs-s.com:8080/api/ 发起一个接口数据请求,查看/cache/nginx目录下的缓存结果:
[root@localhost /]# cat /cache/nginx/b/e1/a88f32c1bd828f3a614ab8584c74ae1b
key: www.blogs.com/api/index.php
http/1.1 200 ok
server: nginx/1.18.0
date: mon, 22 mar 2021 16:23:18 gmt
content-type: text/html; charset=utf-8
content-length: 36
connection: close
x-powered-by: php/7.4.16
{
"message":"this is api","code":304}
[root@localhost e1]#
清除缓存
ngx_cache_purge介绍
ngx_cache_purge是nginx的第三方模块,能够帮助我清除nginx中的缓存。
在之前的nginx编译安装中我们是没有把缓存的清除模块ngx_cache_purge编译进去的,如果启动了缓存,没有安装这个模块,在之后的调试中我们尝试去清除缓存时,将会出现异常:
2021/03/26 11:17:49 [emerg] 12180#0: unknown directive "proxy_cache_purge" in /vhost/blog.conf:24
这个异常是在指示我们,找不到该指令的驱动,需要按照相关模块。
ngx_cache_purge只是nginx的第三方模块,并不是某个特殊的软件,所以我们需要对nginx重新进行编译,操作如下:
./configure --sbin-path=/usr/local/nginx/nginx --conf-path=/usr/local/nginx/nginx.conf --pid-path=/usr/local/nginx/nginx.pid --with-http_gzip_static_module --with-http_stub_status_module --with-file-aio --with-http_realip_module --with-http_ssl_module --with-pcre=/home/pcre-8.44 --with-zlib=/home/zlib-1.2.11 --with-openssl=/home/openssl-1.1.1g --add-module=/home/ngx_cache_purge-2.3
make -j2
make install
配置nginx:
location ~ /clear_cache(.*) {
allow all;
proxy_cache_purge imooc_cache $host$1$is_args$args;
}
再一次启动nginx成功;
接下来进行缓存清除测试,访问:http://blogs.com/clear_cache/api/index.php, 访问这个连接将会清除接口:http://blogs.com/api/index.php 的缓存数据。
结果如下:
控制nginx缓存(如何控制nginx缓存什么数据不缓存什么数据?)
在项目开发中,不可能出现什么都需要缓存的数据,缓存仅仅适合去缓存查询频繁,但是不需要实时更新的数据,这个是它适合的场景,而我们上面的配置,只要是访问api接口目录就会缓存接口的数据,这样对于一些需要实时更新的接口数据来说是不合理的,需要控制好nginx的缓存去缓存什么以及不缓存什么
server
{
.
.
.
location /api/ {
set $a 0;
if ( $request_uri ~ /api/noapi/(.*) ){
set $a 1;
}
proxy_no_cache $a;
.
.
.
}
location ~ /clear_cache(.*) {
allow all;
proxy_cache_purge imooc_cache $host$1$is_args$args;
}
}
set 指令为变量设置,proxy_no_cache参数中的值可以设置多个,但是多个值中,只要有一个是不为0的,就会通过缓存响应数据。
proxy_cache指令详解
- proxy_cache 指令
该指令用于配置一块公用的内存区域的名称,该区域可以存放缓存的索引数据。这些数据在nginx服务器启动时由缓存索引重建进程负责建立,在nginx服务器的整个运行过程中由缓存管理进程负责定时检测过期数据,检索等管理工作。
proxy_cache zone | off;
zone,设置的用于存放缓存索引的内存区域的名称。
off,关闭proxy_cache 功能,是默认的设置。
- proxy_cache_bypass指令
该指令用于配置nginx服务器向客户端发送响应数据时,不从缓存中获取的条件。这些条件支持使用nginx 配置的常用变量。
proxy_cache_bypass string ..;
string为条件变量,支持设置多个,当至少有一个字符串指令不为空或者不等于о时,响应数据不从缓存中获取。
看一个例子:
proxy_cache _bypass $cookie_nocache $arg nocache $sarg_comment $http_pragma $http.authorization;
其中,scookie_nocache、sarg_nocache、sarg_comment、shttp_pragma 和shttp_authorization 都是nginx配置文件的变量,
- proxy_cache_key指令
该指令用于设置nginx服务器在内存中为缓存数据建立索引时使用的关键字
proxy cache key string;
string为设置的关键字,支持变量。
如果我们希望缓存数据包含服务器主机名称等关键字,则可以将该指令设置为:
proxy_cache_key "$scheme$host$request";
- proxy_cache_lock指令
该指令用于设置是否开启缓存的锁功能。在缓存中,某些数据项可以同时被多个请求返回的响应数据填充。开启该功能后,nginx服务器同时只能有一个请求填充缓存中的某一数据项,这相当于给该数据项上锁,不允许其他请求操作。其他的请求如果也想填充该项,必须等待该数据项的锁被释放。这个等待时间由 proxy_cache_lock_timeout 指令配置。
proxy_cache_lock on | off;
默认情况下为关闭
- proxy_cache_lock_timeout指令
该指令用于设置缓存的锁功能开启以后锁的超时时间。具体细节参见proxy_cache_lock 指令的相关内容
proxy cache_ lock_timeout time;
其中,time为设置的时间,默认为5s。
- proxy_cache_min_uses指令
该指令用于设置客户端请求发送的次数,当客户端向被代理服务器发送相同请求达到该指令设定的次数后,nginx服务器才对该请求的响应数据做缓存。合理设置该值可以有效地降低硬盘上缓存数据的数量,并提高缓存的命中率。
proxy_cache_min_uses number;
其中,number为设置的次数。默认设置为1。
- proxy_cache_path指令
该指令用于设置nginx服务器存储缓存数据的路径以及和缓存索引相关的内容
proxy_cache_path [levels=levels] keys_zone=name:sizel [inactive=time1] [max_size=size2][loader_files=number] [loader_sleep=time2]
[loader_threshold-time3];
path,设置缓存数据存放的根路径,该路径应该是预先存在于磁盘上的。levels,设置在相对于path指定目录的第几级hash目录中缓存数据。
levels=1:表示一级hash目录;levels=1:2,表示两级,依次类推。目录的名称是基于请求url通过哈希算法获取到的。
name:sizel,nginx服务器的缓存索引重建进程在内存中为缓存数据建立索引,这一对变量用来设置存放缓存索引的内存区域的名称和大小。
timel,设置强制更新缓存数据的时间,当硬盘上的缓存数据在设定的时间内没有被访问时,nginx服务器就强制从硬盘上将其删除,下次客户端访问该数据时重新缓存。该指令默认设置为10s。
size2、设置硬盘中缓存数据的大小限制。我们知道,硬盘中的缓存源数据由nginx服务器的缓存管理进程进行管理,当缓存的大小超过该变量的设置时,缓存管理进程将根据最近最少被访问的策略删除缓存。
number ,设置缓存索引重建进程每次加载的数据元素的数量上限。在重建缓存索引的过程中,进程通过一系列的递归遍历读取硬盘上的缓存数据目录及缓存数据文件,对每个数据文件中的缓存数据在内存中建立对应的索引,我们称每建立一个索引为加载一个数据元素。进程在每次遍历过程中可以同时加载多个数据元素,该值限制了每次遍历中同时加载的数据元素的数量。默认设置为100。
time2,设置缓存索引重建进程在一次遍历结束、下次遍历开始之间的暂停时长。默认设置为50ms.
time3,设置遍历一次磁盘缓存源数据的时间上限。默认设置为200ms
该指令设置比较复杂,一般需要设置前面三个指令的情形比较多,后面的几个变量与nginx服务器缓存索引重建进程及管理进程的性能相关,一般情况下保持默认设置就可以了。我们来看几个简单的配置实例:
proxy_cache path /nginx/cache/a levels=1 keys_zone=a:10m;
proxy_cache_path /nginx/cache /b levels-2:2 keys_zone=b:100m;
proxy _cache_path /nginx/cache/c levels=1:1:2 keys_zone=c:1000m;
- proxy_cache_use_stale指令
如果nginx在访问被代理服务器过程中出现被代理的服务器无法访问或者访问错误等现象时,nginx服务器可以使用历史缓存响应客户端的请求,这些数据不一定和被代理服务器上最新的数据相一致,但对于更新频率不高的后端服务器来说,nginx服务器的该功能在一定程度上能够为客户端提供不间断访问。该指令用来设置一些状态,当后端被代理的服务器处于这些状态时,nginx服务器启用该功能。
proxy_cache_use_stale error| timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_404 | off..·:
该指令可以支持的状态如语法结构中所示。
- proxy_cache_valid指令
该指令可以针对不同的http响应状态设置不同的缓存时间,
proxy_cache_valid [code...] time;
code,设置http响应的状态代码。该指令可选,如果不设置,nginx服务器只为http状态代码为200、301和302的响应数据做缓存。可以使用“any”表示缓存所有该指令中未设置的其他响应数据。
time,设置缓存时间。看几个例子:
proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1h;
proxy_cache_valid any 1m;
该例子中,对返回状态为200和302的响应数据缓存10分钟,对返回状态为301的响应数据缓存1小时,对返回状态为非200、302和301的响应数据缓存1分钟。
- proxy_no_cache
该指令同于配置在什么情况下不使用cache功能
proxy_no_cache $string...;
string 可以是一个或者都多个变量。当string的值不为空或者不为0时,不启用cache功能
- proxy_store 指令
该指令配置是否在本地磁盘缓存来自被代理服务器的响应数据。这是nginx服务器提供的另一种缓存数据的方法,但是该功能相对 proxy cache简单一些,它不提供缓存过期更新、内存索引建立等功能,不占用内存空间,对静态数据的效果比较好。
proxy_store on | off | string;
on | off,设置是否开启proxy store功能。如果使用变量on,功能开启,缓存文件会存放到alias指令或root指令设置的本地路径下。默认设置为off。
string,自定义缓存文件的存放路径。如果使用变量string,proxy store功能开启,缓存文件会存放到指定的本地路径下。
proxy store方法多使用在被代理服务器端发生错误的情况下,用来缓存被代理服务器的响应数据。
- proxy_store_access指令
该指令用于设置用户或用户组对proxy store缓存的数据的访问权限,
proxy_store_access users:permissions ...
users,可以设置为user、group或者all。
permissions,设置权限。
有关proxy store方法的使用,我们通过官方给出的实例加深理解,在该实例中笔者通过注释对配置做了说明:
1ocation /images/
{
root /data/www;
error_page 404 = /fetch$uri; #定义了404错误的请求页面
}
1ocation /fetch/ #匹配404错误时的请求
{
proxy_pass http://backend;
proxy_store on; #开启proxy store方法
proxy_store_access user:rw group:rw all:r;
root/data/www; #缓存数据的路径
}