团队博客

Nginx 实现缓存

唐增伟  2023-08

一. Nginx 的介绍

众所周知,Nginx 能提供静态服务,同时也能够提供反向代理,同时也能够提供缓存服务。结合 lua 发展而来的 OpenResty 能提供强大的 API 服务,所以说,Nginx 与高速发展的现代互联网相适应,因此,我们也应该学好 Nginx。

二. 缓存介绍

缓存的分类 缓存分为客户端缓存和服务端缓存,当然,每种缓存都有自己的优缺点。对于客户端缓存来说,可以直接读取本地的内容,没有网络消耗,响应最快,缺点是仅仅对该单一的用户生效。而服务端缓存能够对所有用户生效,而且能降低上游服务器的压力,缺点是用户仍然有网络消耗。

三. Nginx 的安装

本人使用的系统是 FreeBSD13.1,各位也可以根据自己的需要选择适合自己系统的 Nginx 版本进行安装。

1.安装 Nginx 包

pkg install nginx

2.安装完成后,配置 rc.conf 使 Nginx 可以开机启动

vim /etc/rc.conf  编辑rc.conf文件,添加nginx_enable="YES",保存退出

3.启动 Nginx

service nginx start

4.查看 Nginx 监听的端口

sockstat -4l
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
www      nginx      1213  7  tcp4   *:80                  *:*
root     nginx      1210  7  tcp4   *:80                  *:*
root     sendmail   1052  5  tcp4   127.0.0.1:25          *:*
root     sshd       821   4  tcp4   *:22                  *:*
root     syslogd    714   7  udp4   *:514                 *:*

可以看到 nginx 已监听在了 80 端口上,至此 nginx 安装完成。

四. 缓存相关指令及使用

1.proxy_cache 定义用来缓存的内存区域, 下面的 zone 是共享内存名称

  • 语法:proxy_cache zone/off

  • 默认值:proxy_cache off;

  • 上下文:http、srver、location

    2.proxy_cache_path 设置缓存的路径和其他其他参数

  • 语法:proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [min_free=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];

  • 默认值:proxy_cache_path off;

  • 上下文:http

具体参数说明

可选参数含义
path缓存文件的存放路径
levelpath 的目录层级
use_temp_pathoff 直接使用 path 路径;on 使用 proxy_temp_path 路径
keys_zonename 是共享内存名称;size 是共享内存大小
inactive在指定时间内没有被访问缓存会被清理;默认 10 分钟
max_size设定最大的缓存空间大小,超过将由 CM(Cache Manager)清理
manager_filesCM 清理一次缓存文件,最大清理文件数;默认 100
manager_sleepCM 清理一次后进程的休眠时间;默认 200 毫秒
manager_thresholdCM 清理一次最长耗时;默认 50 毫秒
loader_filesCL(Cache Loader)载入文件到共享内存,每批最多文件数;默认 100
loader_sleepCL 加载缓存文件到内存后,进程休眠时间;默认 200 毫秒
loader_thresholdCL 每次载入文件到共享内存的最大耗时;默认 50 毫秒

3.proxy_cache_key 决定保存一个缓存的 key

  • 语法:proxy_cache_key string;

  • 默认值:proxy_cache_key $scheme$proxy_host$request_uri;

  • 上下文:http、server、location

    4.proxy_cache_valid 用来设置不同响应状态码的缓存文件的缓存时间

  • 语法: proxy_cache_valid [code ...] time;

  • 默认值: —

  • 上下文: http、server、location

    5.upstream_cache_status 变量缓存的状态,如用来查看缓存是否命中

  • MISS:未命中缓存

  • HIT:命中缓存

  • EXPIRED:缓存过期

  • STALE: 命中了陈旧缓存

  • REVALIDDATED:Nginx 验证陈旧缓存依然有效

  • UPDATING:内容陈旧,但正在更新

  • BYPASS:响应从原始服务器获取

    6.proxy_no_cache 定义不将响应保存到缓存中的条件。如果字符串参数中至少有一个值不为空且不等于 0,则响应将不被保存

  • 语法:proxy_no_cache string;

  • 默认值:-

  • 上下文:http、server、location

    7.proxy_cache_bypass 定义不从缓存获取响应的条件。如果字符串参数中至少有一个值不是空的,并且不等于 0,那么响应将不会从缓存中获取

  • 语法:proxy_cache_bypass string;

  • 默认值:-

  • 上下文:http、server、location

五. 缓存指令在配置文件中配置使用

1.服务器相关信息 服务器一:freebsd_node1 , IP: 192.168.122.243 , 对外提供 http 服务

服务器二:freebsd_node2 , IP: 192.168.122.27 , 作为 freebsd_node1 的上游应用程序服务器

freebsd_node2 的配置文件

编辑/usr/local/etc/nginx/nginx.conf 文件,添加内容如下,让 nginx 监听在不同端口

server {
        listen 1010;
        root /usr/local/www/1010;
        location / {
                index index.html index.htm;
        }
}
server {
        listen 1011;
        root /usr/local/www/1011;
        location / {
                index index.html index.htm;
        }
}

在 freebsd_node2 上,不同的虚拟主机目录下,创建如下文件,并写入不同内容

www ls /usr/local/www/1010
cache.txt  index.html
www ls /usr/local/www/1011
cache.txt  index.html

接下来配置 freebsd_node1

编辑 freebsd_node1 的 nginx 配置文件/usr/local/etc/nginx/nginx.conf,设置如下内容

proxy_cache_path /usr/local/nginx/cache_temp levels=2:2 keys_zone=cache_zone:30m max_size=2g inactive=60m use_temp_path=off;
upstream cache_server {
        server 192.168.122.27:1010;
        server 192.168.122.27:1011;
}
    server {
        listen       80;
        server_name  www.mytest.com;

        location / {
                proxy_cache cache_zone;
                proxy_cache_valid 200 5m;
                add_header  Nginx-Cache-Status  "$upstream_cache_status";
                proxy_pass http://cache_server;
        }
    }

2.配置好后,启动 Nginx

2.1 首先,我们可以测试下没有开启缓存是什么现象,将缓存相关配置注释

location / {
        #proxy_cache cache_zone;
        #proxy_cache_valid 200 5m;
        #add_header  Nginx-Cache-Status  "$upstream_cache_status";
        proxy_pass http://cache_server;
}

向www.mytest.com发起请求,得到如下

for ((i=1;i<=10;i++)); do curl "http://www.mytest.com/cache.txt"; sleep 1; done
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file

没有使用缓存,发生了轮循

2.2 启用缓存

开启 Nginx 缓存

location / {
        proxy_cache cache_zone;
        proxy_cache_valid 200 5m;
        add_header  Nginx-Cache-Status  "$upstream_cache_status";
        proxy_pass http://cache_server;
}

向www.mytest.com发起请求,可以看到

第一次访问,可以看到 Nginx-Cache-Status 显示没有命中

curl www.mytest.com/cache.txt -I
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Thu, 04 Aug 2022 22:33:55 GMT
Content-Type: text/plain
Content-Length: 20
Connection: keep-alive
Last-Modified: Thu, 04 Aug 2022 22:06:55 GMT
ETag: "62ec42ff-14"
Nginx-Cache-Status: MISS
Accept-Ranges: bytes

第二次访问,可以看到 Nginx-Cache-Status 显示为命中

curl www.mytest.com/cache.txt -I
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Thu, 04 Aug 2022 22:33:57 GMT
Content-Type: text/plain
Content-Length: 20
Connection: keep-alive
Last-Modified: Thu, 04 Aug 2022 22:06:55 GMT
ETag: "62ec42ff-14"
Nginx-Cache-Status: HIT
Accept-Ranges: bytes

同时在 freebsd_node1 中也可以看到已有缓存文件出现

在 freebsd_node1 中,查看/usr/local/nginx/cache_temp 目录结构

tree /usr/local/nginx
/usr/local/nginx
└── cache_temp
    └── 76
        └── d1
            └── 608ccf55afd7b17fc84b73d835ecd176

3 directories, 1 file

如果请求文件,可以看到不再轮循,直接使用缓存

在终端执行如下

for ((i=1;i<=10;i++)); do curl "http://www.mytest.com/cache.txt"; sleep 1; done
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file
1011 cache.txt file

六. 配置 Nginx 不缓存特定内容

对于某些更新比较频繁的网页,我们可能不需要缓存,所以接下来我们设置一下如何使 Nginx 不缓存指定内容

1.编辑 freebsd_node1 的 Nginx 配置文件 当请求的 uri 以 txt 结尾时,设置变量值,然后在下面的 proxy_no_cache 中引用

server {
        listen       80;
        server_name  www.mytest.com;

        if ( $request_uri ~ \.(txt)$) {
                set $cookie_name "no cache";
        }

        location / {
                proxy_cache cache_zone;
                proxy_no_cache $cookie_name;
                proxy_cache_valid 200 5m;
                add_header  Nginx-Cache-Status  "$upstream_cache_status";
                proxy_pass http://cache_server;
        }
}

将缓存文件删除

rm -rf  /usr/local/nginx/cache_temp

重启 Nginx

service nginx restart

再发起请求 cache.txt,可以看到发生了轮循

for ((i=1;i<=10;i++)); do curl "http://www.mytest.com/cache.txt"; sleep 1; done
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file
1010 cache.txt file
1011 cache.txt file

多次查看响应头,都是未命中

curl www.mytest.com/cache.txt -I
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Thu, 04 Aug 2022 23:39:09 GMT
Content-Type: text/plain
Content-Length: 20
Connection: keep-alive
Last-Modified: Thu, 04 Aug 2022 22:06:55 GMT
ETag: "62ec42ff-14"
Nginx-Cache-Status: MISS
Accept-Ranges: bytes

七. 总结

在缓存为王的互联网时代,学好缓存是非常重要的,当然也有很多实现缓存的方式,这里只是介绍了 Nginx 如何缓存。Nginx 缓存同样也有很多更深的内容,同样需要我们去探索。

VLAN的基本配置