一 浏览器缓存
1.1 缓存概述
缓存对于 web 至关重要, 尤其对于大型高负载 Web 站点. Nginx 缓存可作为性能优化的一个重要手段, 可以极大减轻后端服务器的负载. 通常对于静态资源, 即较少经常更新的资源, 如图片, CSS 或 JS 等进行缓存, 从而在每次刷新浏览器的时候, 不用重新请求, 而是从缓存里面读取, 这样就可以减轻服务器的压力.
Nginx 设置缓存有两种方式:
proxy_cache_path 和 proxy_cache
Cache-Control 和 Pragma
对于站点中不经常修改的静态内容(如图片, JS,CSS), 可以在服务器中设置 expires 过期时间, 控制浏览器缓存, 达到有效减小带宽流量, 降低服务器压力的目的.
1.2 缓存机制
浏览器无缓存
浏览器请求 ---> 无缓存 ---> 请求 Web 服务器 ---> 请求响应 ---> 呈现
浏览器有缓存
浏览器请求 ---> 有缓存 ---> 校验过期 ---> 是否有更新 ---> 呈现
校验是否过期
Expires HTTP1.0, Cache-Control(max-age) HTTP1.1
协议中 Etag 头信息校验 Etag ()
Last-Modified 头信息校验 Last-Modified (具体时间)
1.3 Nginx 缓存类型
服务器缓存
代理缓存
客户端缓存
1.4 Nginx 代理缓存原理
第一步: 客户端第一次向 Nginx 请求数据 A;
第二步: 当 Nginx 发现缓存中没有数据 A 时, 会向服务端请求数据 A;
第三步: 服务端接收到 Nginx 发来的请求, 则返回数据 A 到 Nginx, 并且缓存在 Nginx;
第四步: Nginx 返回数据 A 给客户端应用;
第五步: 客户端第二次向 Nginx 请求数据 A;
第六步: 当 Nginx 发现缓存中存在数据 A 时, 则不会请求服务端;
第七步: Nginx 把缓存中的数据 A 返回给客户端应用.
1.5 缓存内容
网页缓存是由 HTTP 消息头中的 "Cache-control" 来控制的, 常见的取值有 private,no-cache,max-age,must-revalidate 等, 默认为 private.
其作用根据不同的重新浏览方式分为以下几种情况.
Cache-directive | 说明 |
public | 所有内容都将被缓存(客户端和代理服务器都可缓存)。 |
private | 内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)。 |
no-cache | 必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证停牌(ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。 |
no-store | 所有内容都不会被缓存到缓存或 Internet 临时文件中,强制缓存和对比缓存都不会触发。 |
must-revalidation.proxy-revalidation | 如果缓存内容失败,请求必须发送到服务器、代理以进行重新验证。 |
max-age=xxx(xxx is numeric) | 缓存的内容将在 xxx 秒失效,这个选项只在 HTTP 1.1 可用,并如果和 Last-Modified 一起使用时,优先级较高。 |
1.6 缓存规则
默认情况下, NGINX 尊重 Cache-Control 源服务器的标头. 它不缓存响应 Cache-Control 设置为 Private,No-Cache 或 No-Store 或 Set-Cookie 在响应头. NGINX 只缓存 GET 和 HEAD 客户端请求.
如下配置可覆盖这些默认值:
proxy_buffering 默认为 on, 若 proxy_buffering 设置为 off, 则 NGINX 不会缓存响应.
proxy_ignore_headers 可以配置忽略 Cache-Control:
- location /images/ {
- proxy_cache my_cache;
- proxy_ignore_headers Cache-Control;
- proxy_cache_valid any 30m;
- # ...
- }
二 Nginx 缓存配置项
2.1 expires 配置
语法: expires [modified] time;
expires epoch | max | off;
默认值: expires off; # 静态缓存
作用: Expires 是服务端返回的到期时间. 如果下一次请求如果小于服务端返回的过期时间, 则直接使用缓存数据. Expires 针对 HTTP1.0 的东西, 当前通常浏览器默认都是使用 HTTP1.1. 而且由于该值是有服务端生成, 而客户端的时间和服务端的时间有可能不一致, 导致存在一定误差. 所以 HTTP1.1 使用 Cache-Control 替代.
可配置段: http, server, location, if in location
参数释义:
max 启用后为: Expires: Thu, 31 Dec 2037 23:55:55 GMT Cache-Control: max-age=315360000 (10 年);
epoch 启用后为: Expires: Thu, 01 Jan 1970 00:00:01 GMT Cache-Control: no-cache;
time: 设定具体时间, 可以携带单位(通过 @), 如: 表示一天内的下午 3 点 30 分后失效 expires @15h@30m;time 是负数: 表示 "Cache-Control: no-cache";time 是正数或零:"Cache-Control: max-age=t", 其中 t 单位为秒.
配置示例:
- server {
- listen 80;
- server_name xxx.xxx.com;
- root /App/xxx/html/;
- location ~ .*\.(?:jpg|jpeg|gif|PNG|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm)$
- {
- expires 7d;
- }
- location ~ .*\.(?:JS|CSS)$
- {
- expires 7d;
- }
- location ~ .*\.(?:htm|HTML)$ #不缓存 HTML
- {
- add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
- }
- }
对于 http 协议头 Cache-Control, 其值释义如下:
Public: 指示响应可被任何缓存区缓存.
Private: 指示对于单个用户的整个或部分响应消息, 不能被共享缓存处理. 这允许服务器仅仅描述当用户的部分响应消息, 此响应消息对于其他用户的请求无效.
no-cache: 指示请求或响应消息不能缓存.
no-store: 用于防止重要的信息被无意的发布. 在请求消息中发送将使得请求和响应消息都不使用缓存.
max-age: 指示客户机可以接收生存期不大于指定时间 (以秒为单位) 的响应.
min-fresh: 指示客户机可以接收响应时间小于当前时间加上指定时间的响应.
max-stale: 指示客户机可以接收超出超时期间的响应消息. 如果指定 max-stale 消息的值, 那么客户机可以接收超出超时期指定值之内的响应消息.
2.2 proxy_cache 配置
语法: proxy_cache zone | off;
默认: proxy_cache off;
可配置段: http, server, location
作用: 设置是否开启对后端响应的缓存, 如果开启的话, 参数值就是 zone 的名称.
示例:
1 proxy_cache mycache;
2.3 proxy_cache_path 配置
语法: 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];
默认值:--
可配置段: http
作用: 指定缓存位置, 缓存名称, 内存中缓存内容元数据信息大小限制, 缓存总大小限制. 缓存位置是一个目录应该先创建好, nginx 并不会帮我们创建这个缓存目录.
参数释义:
path: 定义缓存文件存放位置;
levels: 定义缓存路径的目录层级, 默认所有缓存文件都放在上面指定的根路径中, 最多三级, 每层目录长度为 1 或 2 字节;
keys_zone:name 表示共享内存名称, 用于在共享内存中定义一块存储区域来存放缓存的 key 和 metadata(类似于使用次数), 这样 nginx 可以快速判断一个 request 是否命中缓存. 由 proxy_cache 指令使用; size 表示共享内存大小, 1mb 大约可以存放 8000 个 key;
max_size: 设置缓存大小的上限. 它是可选的, 不指定值允许缓存增长以使用所有可用磁盘空间. 当缓存大小达到限制时, 称为缓存管理器的进程将删除最近最少用于将缓存大小恢复到限制之下的文件;
inactive: 在 inactive 时间内没有被访问的缓存会被淘汰掉, 默认是 10 分钟;
use_temp_path: 如果为 off, 则 nginx 会将缓存文件直接写入指定的 cache 文件中, 而不使用 temp_path 指定的临时存储路径.
注意: inactive 和 expired 配置项的含义是不同的, expired 只是判断过期时间, 不会删除缓存; 而 inactive 是直接删除过期缓存.
配置示例:
- http {
- ...
- // 缓存目录:/data/nginx/cache
- // 缓存名称: one
- // 缓存占用内存空间: 10m
- // 缓存目录级别为 2
- // 缓存最大时间为 60 分钟
- // 加载器每次迭代过程最多执行 300 毫秒
- // 加载器每次迭代过程中最多加载 200 个文件
- // 缓存硬盘空间最多为 200m
- proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m inactive=60m loader_threshold=300 loader_files=200 max_size=200m;
- server {
- listen 8080;
- // 使用名称为 one 的缓存
- proxy_cache one;
- location / {
- // 此 location 中使用默认的缓存配置
- proxy_pass http://backend1;
- }
- location /some/path {
- proxy_pass http://backend2;
- // 缓存有效期为 1 分钟
- proxy_cache_valid any 1m;
- // 被请求 3 次以上时才缓存
- proxy_cache_min_uses 3;
- // 请求中有下面参数值时不走缓存
- proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
- }
- }
- }
提示: 在如上缓存工作中有两个附加进程:
缓存管理器: 定期检查缓存状态, 看缓存总量是否超出限制, 如果超出, 就移除其中最少使用的部分
缓存加载器: 加载器只在 nginx 启动后运行一次, 把缓存内容的元数据信息加载到内存空间, 如果一次性加载全部缓存信息, 会大量消耗资源, 使 nginx 在启动后的几分钟里变慢, 为避免此问题, 有 3 种加载策略:
loader_threshold: 指定每次加载执行的时间
loader_files: 每次最多加载的数量
loader_sleeps: 每次加载的延时
2.3 proxy_cache_valid 配置
语法: proxy_cache_valid [code ...] time;
默认值:--
可配置段: http, server, location
作用: 默认情况下, 缓存的内容是长期存留的, 除非缓存的总量超出限制, 此字段可配置不同的响应码缓存不同的时长, 即指定缓存的有效期.
示例:
响应状态码为 200 302 时, 10 分钟有效;
响应状态码为 404 时, 1 分钟有效;
- ......
- proxy_cache_valid 200 302 10m;
- proxy_cache_valid 404 1m;
- ......
对应任何状态码, 5 分钟有效;
- ......
- proxy_cache_valid any 5m;
- ......
2.4 proxy_cache_methods 配置
语法: proxy_cache_methods GET | HEAD | POST ...;
默认值: proxy_cache_methods GET HEAD;
可配置段: http, server, location
作用: 对哪些方法的请求进行缓存.
提示: 更多缓存配置参考: https://shuwoom.com/?p=4311,https://linux.cn/article-5945-1.html.
第三方缓存模块参考: https://www.jianshu.com/p/1ba7d91afa39.
2.5 proxy_cache_key string
语法: proxy_cache_key string;
默认值: proxy_cache_key $scheme$proxy_host$request
可配置段: http, server, location
作用: 用于设置不同维度进行缓存, 即给缓存设定 key. 如缓存 url.
示例:
2.6 proxy_cache_min_uses
语法: proxy_cache_min_uses string;
默认值: proxy_cache_min_uses 1;
可配置段: http, server, location
作用: 指定请求至少被发送了多少次以上时才缓存, 可以防止低频请求被缓存.
示例:
- ......
- proxy_cache_min_uses 5;
- ......
- 2.7 proxy_cache_bypass
语法: proxy_cache_bypass string;
默认值:--
可配置段: http, server, location
作用: 指定哪些响应在某些值不为空或不为 0 的情况下不走缓存.
示例:
- ......
- proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
- ......
- 2.8 proxy_no_chache string
语法: proxy_no_chache string;
默认值:--
可配置段: http, server, location
作用: 指定定哪些请求不被缓存, 即响应来自原始服务器而不是缓存.
示例:
- ......
- proxy_no_chache $cookie_nocache $arg_nocache $arg_nocache;
- ......
- 2.9 proxy_cache_use_stale
语法: proxy_cache_use_stale off | on;
默认值: proxy_cache_use_stale off;
可配置段: http, server, location
作用: 指定在后端服务器在返回什么状态码的情况下可以使用过期的缓存.
示例:
- ......
- proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
- ......
- 2.10 proxy_cache_lock
语法: proxy_cache_lock off | on;
默认值: proxy_cache_lock off;
可配置段: http, server, location
作用: 默认不开启, 开启的话则每次只能有一个请求更新相同的缓存, 其他请求要么等待缓存有数据要么限时等待锁释放. 通常在多个客户端请求缓存未命中时, 只有第一个请求可以发向原服务器, 其他请求要等待第一个响应返回或者超时后, 使用缓存响应客户端. 该参数可以合并回源请求, 减轻峰值流量下的压力.
示例:
- ......
- proxy_cache_lock on;
- ......
- 2.11 proxy_cache_lock_timeout
语法: proxy_cache_lock_timeout time;
默认值: proxy_cache_lock_timeout 5s;
可配置段: http, server, location
作用: 等待缓存锁超时之后将直接请求后端, 结果不会被缓存.
示例:
- ......
- proxy_cache_lock_timeout 5s;
- ......
三 缓存配置实例
提示: 本实验结合反向代理演示最佳, 具体配置参考《010.Nginx 正反代理》步骤六.
参考文档: https://www.myfreax.com/nginx-caching-guide/ .
四 缓存清除
4.1 清除缓存配置
- location ~ /purge(/.*) {
- allow 127.0.0.1;
- allow 192.168.55.0/24;
- deny all;
- proxy_cache_purge cache_one $1$is_args$args;
- }
注意: 使用 proxy_cache_purge 清除缓存, 必须提前安装 ngx_cache_purge 模块, 安装模块必须基于编译安装的 Nginx. 之后使用 url 访问即可清除对应缓存, 如 cache.linuxds.com/purge/nginx.PNG 即可清除 cache.linuxds.com/nginx.PNG 此文件的缓存.
4.2 脚本清除
清除缓存脚本如下, 必须在缓存服务器上执行,
- [root@nginx01 ~]# vi nginx_cache_clean.sh
- #!/bin/sh
- #****************************************************************#
- # ScriptName: nginx_cache_clean.sh
- # Author: null
- # Create Date: 2020-06-24 00:03
- # Modify Author: xhy
- # Modify Date: 2020-06-24 00:03
- # Version:
- #***************************************************************#
- echo -e "\n"
- echo -n -e "\e[35;1m 请输入 Nginx Proxy_cache 缓存的具体路径(提示: 可使用 Tab 补全!)\e[0m\e[34;5m:\e[0m"
- read -e path
- CACHE_DIR=$path
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -n -e "\e[32;1m 请输入删除操作的类型:\n1. 按文件类型删除 \ t2. 按具体文件名删除 \ t3. 按文件目录删除 \ n:"
- read action
- case $action in
- 1)
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -n -e "\e[34;1m 请输入你要删除的缓存文件类型(多个参数可空格隔开)\e[0m\e[34;5m:\e[0m"
- read -a FILE
- for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
- do
- grep -r -a \.$i ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'> /tmp/cache_list.txt
- for j in `cat /tmp/cache_list.txt`
- do
- rm -rf $j
- echo "$i $j 删除成功!"
- done
- done
- ;;
- 2)
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -n -e "\e[33;1m 请输入你要删除的缓存文件具体名称(多个参数可空格隔开)\e[0m\e[34;5m:\e[0m"
- read -a FILE
- for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
- do
- grep -r -a $i ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'> /tmp/cache_list.txt
- for j in `cat /tmp/cache_list.txt`
- do
- rm -rf $j
- echo "$i $j 删除成功!"
- done
- done
- ;;
- 3)
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -e "\e[32;1m----------------------------------------------------------------\e[0m"
- echo -n -e "\e[33;1m 支持的模式有:\n1. 清除网站 cache 目录下的所有缓存: cache.aa.com/data/cache/\n2. 清除网站 shop 下的所有缓存: cache.aa.com/data/upload/shop\n3. 清除网站根目录下的所有缓存: cache.aa.com\e[0m\n"
- echo -n -e "\e[34;1m 请输入你要删除的缓存文件具体目录 \ e[0m\e[34;5m:\e[0m"
- read -a FILE
- for i in `echo ${FILE[*]}|sed 's/ /\n/g'`
- do
- grep -r -a "$i" ${CACHE_DIR}| awk 'BEGIN {FS=":"} {print $1}'> /tmp/cache_list.txt
- for j in `cat /tmp/cache_list.txt`
- do
- rm -rf $j
- echo "$i $j 删除成功!"
- done
- done
- ;;
- *)
- echo "输入错误, 请重新输入"
- ;;
- esac
参考文档: https://lichi6174.github.io/nginx-cache/.
来源: https://www.cnblogs.com/itzgr/p/13321980.html