Nginx中的缓存与压缩配置

1. Nginx中的缓存介绍

由于 Nginx 是在网站的所有其他后台服务的最前线,它接收的请求和流量是后台服务的数倍甚至数十倍之多。因此,用好 Nginx 的缓存功能对于大型网站而言至关重要。Nginx 中的缓存功能优势如下:

bash 复制代码
提升所有客户端体验
有效降低上游服务器的负载
减少上游服务器之间的流量消耗

Nginx 的 Web 缓存服务主要由 proxy_cache 相关指令集和 fastcgi_cache 相关指令集构成,前者用于反向代理时,对后端内容源服务器进行缓存,后者主要用于对 FastCGI 的动态程序进行缓存。两者的功能基本上一样。强大的缓存功能也成为了 Nginx 吸引众多用户的重要因素之一。

2. Nginx中缓存指令

2.1 expires指令

Nginx 中的 expires 指令通过控制 HTTP 相应中的" Expires" 和 "Cache-Control"的头部值,达到控制浏览器缓存时间的效果。指令格式如下:

bash 复制代码
Syntax:	expires [modified] time;
expires epoch | max | off;
Default:	
expires off;
Context: http, server, location, if in location

Nginx 中的时间单位有s(秒), m(分), h(小), d(天)。指令参数说明:

bash 复制代码
epoch: 指定"Expires"的值为1, 即 January,1970,00:00:01 GMT;
max: 指定"Expires"的值为31 December2037 23:59:59GMT, "Cache-Control"的值为10年;
-1:指定"Expires"的值为当前服务器时间-1s,即永远过期;
off:不修改"Expires"和"Cache-Control"的值
time中出现@表示具体的时间,比如@18h30m表示的是下午6点半;

官方的示例如下:

bash 复制代码
expires    24h;       # 24小时过期
expires    modified +24h;
expires    @24h;
expires    0;         # 不缓存,立即过期
expires    -1;        # 用不过期
expires    epoch;
expires    $expires;

2.2 proxy 模块中的 cache 相关指令

Nginx 的 proxy 模块中定义了许多和 cache 相关的模块,这是配置 http 请求代理的缓存功能。

通常情况下,我们使用 proxy_cache 指令开启 Nginx 缓存功能,用 proxy_cache_path 指令来设置缓存的路径和其他配置。两个指令的用法如下:

bash 复制代码
Syntax:	proxy_cache zone | off;
Default: proxy_cache off;
Context: http, server, location

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

proxy_cache_path 指令中有较多的参数,部分重要参数说明如下:

bash 复制代码
path: 定义缓存存放的位置;
levels: 定义缓存路径的目录等级,最多3级
use_temp_path:
on: 使用proxy_temp_path定义的目录
off:
keys_zone:
name: 共享内存名
size: 共享内存大小
max_size: 设置最大的缓存文件大小

其余的重要的缓存指令有:

proxy_cache_key: 配置缓存的关键字,格式如下:

bash 复制代码
Syntax:	proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location

示例:

bash 复制代码
proxy_cache_key "$host$request_uri $cookie_user";

proxy_cache_valid: 配置缓存什么样的响应,缓存多长时间。注意,如果只设置了缓存时间,只缓存只针对相应码200, 301和302的请求 。格式如下:

bash 复制代码
Syntax:	proxy_cache_valid [code ...] time;
Default: ---
Context: http, server, location

示例:

bash 复制代码
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404      1m;

# 只设置了缓存时间,只对200,301和302有效
proxy_cache_valid 5m;

proxy_cache_valid 200 302 10m;
proxy_cache_valid 301      1h;

# any表示所有相应码
proxy_cache_valid any      1m;

proxy_cache_methods: 对哪种 method 的请求使用缓存返回响应。

bash 复制代码
Syntax:	proxy_cache_methods GET | HEAD | POST ...;
Default: proxy_cache_methods GET HEAD;
Context: http, server, location

3. Nginx中的压缩配置

Nginx 的压缩配置主要是用在与浏览交互中,对网页、css、js等静态资源进行压缩,通过消耗 cpu 的计算资源来节约大量的带宽,提高传输效率,给用户良好的体验。Nginx 中的 ngx_http_gzip_module 就是专门处理这里压缩功能的模块。其中部分重要指如下:

gzip: 是否打开 gzip 压缩功能;

bash 复制代码
Syntax:	gzip on | off;
Default: gzip off;
Context: http, server, location, if in location

gzip_buffers: 设置压缩所需要的缓冲区大小;

bash 复制代码
Syntax:	gzip_buffers number size;
Default: gzip_buffers 32 4k|16 8k;
Context: http, server, location

gzip_comp_level: 设置压缩级别,从1-9;越大压缩率越高,同时消耗cpu资源也越多;

bash 复制代码
Syntax:	gzip_comp_level level;
Default: gzip_comp_level 1;
Context: http, server, location

gzip_types:需要压缩的文件格式 text/html默认会压缩,不用添加;

bash 复制代码
Syntax:	gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location

gzip_min_length: 压缩文件最小大小;

bash 复制代码
Syntax:	gzip_min_length length;
Default: gzip_min_length 20;
Context: http, server, location

一个常见的压缩配置如下:

bash 复制代码
 # 开启gzip压缩
    gzip on;
    # http的协议版本
    gzip_http_version 1.0;
    # IE版本1-6不支持gzip压缩,关闭
    gzip_disable 'MSIE[1-6].';
    #需要压缩的文件格式
    gzip_types text/css text/javascript application/javascript image/jpeg image/png image/gif;
    #设置为4个8K内存作为压缩结果流缓存
    gzip_buffers 4 8k;
    #压缩文件最小大小
    gzip_min_length 1k;
    #压缩级别1-9
    gzip_comp_level 9;
    #给响应头加个vary,告知客户端能否缓存
    gzip_vary on;
    #反向代理时使用
    gzip_proxied off;
注意: gzip 的开启需适应特定的场景,比如大文件和图片的传输就不是和开启 gzip 功能,压缩效果不明显的同时还白白耗费系统的资源,所以使用时需要慎重考虑。

4. 案例实战

4.1 expires 指令用法

首先准备 nginx.conf,中间简单配置几条 expires 指令用作测试:

bash 复制代码
...

http{
    server {
        listen 8000;
        location / {
            default_type text/plain;
            expires 10m;
            #expires -1h;
            return 200 '8000, server\n';
        }
    }
}

...

下面观察请求结果:

bash 复制代码
# 使用 expires 10m 配置,可以看到Expires值正好为10分钟后
[shen@shen ~]$ curl http://180.76.152.113:8000 -I
HTTP/1.1 200 OK
Server: nginx/1.17.6
Date: Thu, 06 Feb 2020 11:37:17 GMT
Content-Type: text/plain
Content-Length: 13
Connection: keep-alive
Expires: Thu, 06 Feb 2020 11:47:17 GMT
Cache-Control: max-age=600

# 使用 expires -1h 配置, -1h表示环境一个小时前过期了,所以返回Cache-Control的值为no-cache
[shen@shen ~]$ curl http://180.76.152.113:8000 -I
HTTP/1.1 200 OK
Server: nginx/1.17.6
Date: Thu, 06 Feb 2020 11:37:32 GMT
Content-Type: text/plain
Content-Length: 13
Connection: keep-alive
Expires: Thu, 06 Feb 2020 10:37:32 GMT
Cache-Control: no-cache

4.2 proxy_cache 缓存实验

准备好 proxy_cache 缓存相关的配置,如下:

bash 复制代码
...

http {
    
    server {
        listen 8000;
        location / {
            default_type text/plain;
            return 200 '8000, server\n';
        }
    }

    server {
        listen 8001;
        location / {
            default_type text/plain;
            return 200 '8001, server\n';
        }
    }

    server {
        listen 8002;
        location / {
            default_type text/plain;
            return 200 '8002, server\n';
        }
    }
    
    # 定义上游服务器
    upstream backends {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
    }
    
    # proxy_cache_path 指令
    proxy_cache_path /root/test/cache levels=1:2 keys_zone=nginx_cache:10m max_size=10g inactive=60m use_temp_path=off;
    
    server {
       listen  80;

       location / {
          proxy_pass http://backends;
          proxy_cache nginx_cache;
          # 状态码为200和301的缓存1分钟
          proxy_cache_valid 200 301 1m;
          # 其余的缓存10分钟
          proxy_cache_valid any 10m;
          # response响应的头信息中定义缓存的状态(有没有命中)
          proxy_cache_key "$host$uri$is_args$args";
          expires 1d;
          proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
          proxy_no_cache $http_pragma    $http_authorization;
          # add_header 响应添加缓冲命中结果
          add_header Nginx-Cache "$upstream_cache_status";
       }
    
}

...

通过 curl 命令向 Nginx 所在主机的 80端 请求,第一次请求转发到8000端口,结果被缓存; 第2-3次请求时由缓存返回结果,所以仍然是8000端口的返回;等待超过1分钟后,缓存失效,请求被转发到8001端口进行处理,返回相应结果;最后再次请求80端口,依旧由缓存命中,返回8001端口的响应结果。参看日志记录的 http 请求。

bash 复制代码
# 第一次请求,转到8000端口响应,然后缓存
[shen@shen ~]$ curl http://180.76.152.113
8000, server
# 接下来请求全部由缓存命中
[shen@shen ~]$ curl http://180.76.152.113
8000, server
[shen@shen ~]$ curl http://180.76.152.113
8000, server
[shen@shen ~]$ curl http://180.76.152.113
8000, server
# 缓存失效,转发到8001端口相应,并缓存结果
[shen@shen ~]$ curl http://180.76.152.113
8001, server
# 继续命中缓存
[shen@shen ~]$ curl http://180.76.152.113
8001, server

查看请求的响应结果:

bash 复制代码
[root@server sbin]# tail -f ../logs/access.log

127.0.0.1 - - [06/Feb/2020:20:14:15 +0800] "GET / HTTP/1.0" 200 13 "-" "curl/7.29.0" "-""-"
103.46.244.69 - - [06/Feb/2020:20:14:15 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-""MISS"
103.46.244.69 - - [06/Feb/2020:20:14:23 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-""HIT"
103.46.244.69 - - [06/Feb/2020:20:14:26 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-""HIT"
127.0.0.1 - - [06/Feb/2020:20:16:10 +0800] "GET / HTTP/1.0" 200 13 "-" "curl/7.29.0" "-""-"
103.46.244.69 - - [06/Feb/2020:20:16:10 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-""EXPIRED"
103.46.244.69 - - [06/Feb/2020:20:16:22 +0800] "GET / HTTP/1.1" 200 13 "-" "curl/7.29.0" "-""HIT"

5. 小结

Nginx 中的缓存功能。一个是针对浏览器的缓存控制,另一个是针对上游服务器对 http 请求进行缓存,以减轻上游服务器的负载,这在高流量场景下是非常必要的。接下来,我们完成两个实验,测试前面讲到的缓存指令,并实际观察缓存效果。

相关推荐
facaixxx20242 小时前
什么是巨型帧Jumbo Frames?云服务器开启巨型帧有什么用?
运维·服务器
巨可爱熊4 小时前
高并发内存池(定长内存池基础)
linux·运维·服务器·c++·算法
zkmall4 小时前
ZKmall开源商城静态资源管理:Nginx 配置与优化
运维·nginx·开源
美味的大香蕉6 小时前
Spark SQL
笔记
yangang1856 小时前
linuxbash原理
linux·运维·服务器
轻闲一号机7 小时前
【机器学习】机器学习笔记
人工智能·笔记·机器学习
小度爱学习7 小时前
linux中的执行命令格式及命令帮助
linux·运维·chrome
yangshuo12817 小时前
如何在服务器上搭建mail服务器邮件服务器
运维·服务器
猿小喵7 小时前
记录一次TDSQL网关夯住故障
运维·数据库·mysql
天下琴川7 小时前
Dify智能体平台源码二次开发笔记(5) - 多租户的SAAS版实现(2)
人工智能·笔记