前言:本文的Nginx使用版本为:1.14.2

在Web应用中,用户打开一个页面或者加载一个请求耗时过长时,体验是非常差的。这个时间可能受到很多因素影响,比如:

  • 建立连接慢
  • 服务器响应较慢(Waiting)
  • 页面资源大,包括js/css等(Downloading)
  • 接口内容大(Downloading)

正常情况下,在响应和传输上花费的时间比例是最多的。

假设我们的请求连接一下子建立完成,同时服务器的响应足够快,那么剩下的就是传输问题。
或许可以选择在硬件上提高速度,比如用户手机从2g信号提升到4g,宽带速度从10M提到200M,服务器的带宽也跟着提高。
可是用户端对于我们来说不可控,服务端的带宽资源相对还是比较昂贵。这时候,可以对传输的数据做压缩处理。假设资源文件能从5兆压缩到1兆,那便是5倍的性能提升。

为Nginx开启gzip压缩

Nginx是一个高性能的HTTP和反向代理服务器,默认提供了gzip的压缩模块:ngx_http_gzip_module
模块的最开头便介绍道:能帮助我们减少一半甚至更多的传输数据大小

gzip模块默认是没有开启的,我们可以在httpserverlocation配置中开启它。

这是官方的配置例子:

1
2
3
4
5
6
7
8
9
server{

gzip on; # 开启gzip
gzip_types text/plain application/xml; # 进行压缩的类型
gzip_proxied no-cache no-store private expired auth; # 根据某些头部决定是否压缩,在下文详细分析
gzip_min_length 1000; # 最小的压缩长度

...
}

通过配置开启了gzip压缩,体验传输速度的提升吧。

gzip_module有许多详细的配置参数。

配置名 参数内容 默认值 描述
gzip on | off off 是否开启gzip
gzip_buffers number size 32 4k | 16 8k 压缩的buffers的数量和大小,默认值取决于系统一个内存页的大小
gzip_comp_level number 1 压缩的级别,值的范围是1到9
gzip_disable 正则表达式 假如User-Agent符合正则规则,则关闭压缩功能
gzip_http_version 1.0 | 1.1 1.1 设置压缩时最低的http版本
gzip_min_length length 20 启用压缩的response最低长度
gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any off 详见下文说明
gzip_types mine-type … text/html 要压缩MINE-TYPE类型,设置为*时会匹配所有的MIME (0.8.29)类型
gzip_vary on | off off 开启时,会在返回头插入”Vary: Accept-Encoding”

同时,启用了模块我们可以在配置中使用内置变量$gzip_ratio,它的值是压缩率。

比较难理解的参数:gzip_proxied

这个模块中有一个配置gzip_proxied,对这个配置疑惑的人比较多。在了解这个配置前,我们先看下http的头部Via
Via头在代理服务器中传播时会被加上(不管是正向代理还是反向代理)。通过这个头部,服务器就可以知道请求经过了哪些代理。

回到gzip_proxied,默认情况下,nginx不会对被代理的请求进行压缩,它通过Via头识别请求是不是被代理过。如果要对被代理的请求进行压缩,可以配置这个参数,比如前文的:

1
gzip_proxied no-cache no-store private expired auth;

它可以配多个值,分别为:

参数名 描述
off 不压缩所有被代理的请求
expired 如果返回头包含Expires,则开启压缩
no-cached 如果返回头包含Cache-Control,值为no-cache,则开启压缩
no-store 如果返回头包含Cache-Control,值为no-store,则开启压缩
private 如果返回头包含Cache-Control,值为private,则开启压缩
no_last_modified 如果返回头没有包含Last-Modified,则开启压缩
no_etag 如果返回头没有包含ETag,则开启压缩
auth 如果请求头包含Authorization,则开启压缩
any 压缩所有被代理请求

写在最后

开启压缩,能让我们的用户体验大大提升,同时节省服务器的带宽资源。然而压缩功能的开启,会消耗服务器的计算资源,需要衡量资源是否需要进行压缩、以及压缩的级别。
在web应用中,很多资源文件可能在构建项目时已经经过处理,那么可以不对它们进行压缩,这时可以由gzip模块的gzip_types具体配置。

总的来讲,压缩是一个可以提升性能的功能,但同时也是需要我们去衡量后,做出最好的配置调整。

参考

ngx_http_gzip_module
Via - HTTP | MDN