15《Nginx 入门教程》Nginx中的缓存与压缩配置

1. Nginx中的缓存介绍

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

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

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

2. Nginx中缓存指令

2.1 expires指令

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

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

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

  • 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点半;

官方的示例如下:

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 指令来设置缓存的路径和其他配置。两个指令的用法如下:

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
代码块1234567

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

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

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

  • proxy_cache_key: 配置缓存的关键字,格式如下:
Syntax: proxy_cache_key string;
Default: proxy_cache_key $scheme$proxy_host$request_uri;
Context: http, server, location
代码块123

示例:

proxy_cache_key "$host$request_uri $cookie_user";
代码块1
  • proxy_cache_valid: 配置缓存什么样的响应,缓存多长时间。注意,如果只设置了缓存时间,只缓存只针对相应码200, 301和302的请求 。格式如下:
Syntax: proxy_cache_valid [code ...] time;
Default: —
Context: http, server, location
代码块123

示例:

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;

代码块123456789101112
  • proxy_cache_methods: 对哪种 method 的请求使用缓存返回响应。
Syntax: proxy_cache_methods GET | HEAD | POST ...;
Default: proxy_cache_methods GET HEAD;
Context: http, server, location
代码块123

3. Nginx中的压缩配置

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

  • gzip: 是否打开 gzip 压缩功能;
Syntax: gzip on | off;
Default: gzip off;
Context: http, server, location, if in location

  • gzip_buffers: 设置压缩所需要的缓冲区大小;
Syntax: gzip_buffers number size;
Default: gzip_buffers 32 4k|16 8k;
Context: http, server, location

  • gzip_comp_level: 设置压缩级别,从1-9;越大压缩率越高,同时消耗cpu资源也越多;
Syntax: gzip_comp_level level;
Default: gzip_comp_level 1;
Context: http, server, location

  • gzip_types:需要压缩的文件格式 text/html默认会压缩,不用添加;
Syntax: gzip_types mime-type ...;
Default: gzip_types text/html;
Context: http, server, location

  • gzip_min_length: 压缩文件最小大小;
Syntax: gzip_min_length length;
Default: gzip_min_length 20;
Context: http, server, location

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

    # 开启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 指令用作测试:

...

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

...

下面观察请求结果:

# 使用 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 缓存相关的配置,如下:

...

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 请求。

# 第一次请求,转到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

查看请求的响应结果:

[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"

代码块12345678910

5. 小结

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容