6 gzip 压缩
6 gzip 压缩
TIP
本小节主要介绍以下知识:
- Gzip 各模块支持的配置指令
- Gzip 压缩功能的使用
- Gzip 压缩功能常见问题的解决
概述
在 Nginx 配置文件中可以配置 Gzip 的使用,相关指令可以在配置文件 http 块、server 块或者 location 块中设置,Nginx 服务器通过 ngx_http_gzipz_module 模块、ngx_http_gzip_static_module 模块和ngx_http_gunzip_module 模块对这些指令进行解析和处理。
由 ngx_http_gzip_module 模块处理的 9 个指令
ngx_http_gzip_module 模块主要负责 Gzip 功能的开启和设置,对响应数据进行实时压缩。该模块主要包括以下指令:
gzip 指令
该指令用于开启或者关闭 Gzip 功能,语法结构为gzip on|off;
,默认情况下,该指令设置为 off,即不启用 Gzip 功能。gzip_buffers 指令
该指令用于设置 Gzip 压缩文件使用缓存空间的大小,语法结构为:gzip_buffers number size;
- number,指定 Nginx 服务器需要向系统申请缓存空间的个数。
- size,指定每个缓存空间的大小。
默认情况下 number * size 的值为128,其中 size 的值取系统内存页一页的大小,为 4KB 或者 8KB,即:gzip_buffers 32 4K | 16 8K;
。
gzip_comp_level 指令
该指令用于设定 Gzip 压缩程度,包括级别 1 到级别 9。级别 1 表示压缩程度最低,压缩效率最高;级别 9 表示压缩成都最高,压缩效率最低,最废时间。语法结构为:gzip_comp_level level;
,默认值设置为级别 1。gzip_disable 指令
针对不同种类客户端发起的请求,可以选择性地开启或关闭 Gzip 功能。该指令从 Nginx0.6.23 启用,用于设置一些客户端种类。Nginx 服务器在响应这些种类的客户端请求时,不适用 Gzip 功能缓存响应输出数据。语法结构为:gzip_disable regex ...;
其中,regex 根据客户端的浏览器标志(User-Agent,UA)进行设置,支持使用正则表达式。
一个示例配置:gzip_disable MSIE [4-6]\.;
,响应这些浏览器(IE)发出的请求时,Nginx 服务器不进行 Gzip 压缩。gzip_http_version 指令
针对不同的 HTTP 协议版本,需要选择性地开启或者关闭 Gzip 功能。语法结构为:gzip_http_version 1.0|1.1;
默认设置为 1.1 版本,即只有客户端使用 1.1 及以上版本的 HTTP 协议时,才使用 Gzip 功能响应输出数据进行压缩。从目前来看,绝大多数的浏览器都支持 Gzip 自解压,一般采用默认值即可。gzip_min_length 指令
Gzip 压缩功能对大数据的压缩明显,但是如果压缩很小的数据,可能出现越压缩数据量越大的情况,因此应该根据响应页面的大小,选择性的开启或关闭 Gzip 功能。
该指令设置页面的字节数,当响应页面的大小大于该值时,才启用 Gzip 功能。响应页面的大小通过 HTTP 响应头部中的 Content-Length 指令获取,但是如果使用了 Chunk 编码动态压缩,Content-Length 或不存在或被忽略,该指令不起作用。语法结构为:gzip_min_length length;
默认值为 20,设置为 0 时表示不管响应页面大小如何通通压缩,建议设置为 1KB,即:gzip_min_length 1024;
。gzip_proxied 指令
该指令在使用 Nginx 服务器的反向代理功能时有效,前提是在后端服务器返回的响应页头部中,Requests 部分包含用于通知代理服务器的 Via 头域。
它主要用于设置 Nginx 服务器是对后端服务器返回的结果进行 Gzip 压缩。语法结构为:gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag| auth | any...;
- off,关闭 Nginx 服务器对后端服务器返回结果的 Gzip 压缩,这是默认设置。
- expired,当后端服务器响应页头部包含用于指示响应数据过期时间的 expired 头域时,启用对响应数据的 Gzip 压缩。
- no-cache,当后端服务器响应页头部包含用于通知所有缓存机制是否缓存的 Cache-Control 头域、且其指令值为 no-cache 时,启用对响应数据的 Gzip 压缩。
- no-store,当后端服务器响应页头部包含用于通知所有缓存机制是否缓存的 Cache-Control 头域、且其指令值为 no-store 时,启用对响应数据的 Gzip 压缩。
- private,当后端服务器响应页头部包含用于通知所有缓存机制是否缓存的 Cache-Control 头域、且其指令值为 private 时,启用对响应数据的 Gzip 压缩。
- no_last_modified,当后端服务器响应页头部不包含用于指明需要获取数据最后修改时间的 Last-Modified 头域时,启用对响应数据的 Gzip 压缩。
- no_etag,当后端服务器响应页头部不包含用于标示请求变量的实体值 ETag 头域时,启用对响应数据的 Gzip 压缩。
- auth,当后端服务器响应页头部包含用于标示 HTTP 授权证书的 Authorization 头域时,启用对响应数据的 Gzip 压缩。
- any,无条件启用对响应数据的 Gzip 压缩。
该指令的设置需要对 HTTP 协议的 HTTP Header 消息有基本的了解。
gzip_types 指令
Nginx 服务器可以根据响应页的 MIME 类型选择性的开启 Gzip 压缩功能。
该指令用来设置 MIME 类型,被设置的类型将被压缩,注意需要 gzip 指令设置为 on。语法结构为:gzip_types mime-type ...;
其中,mime-type 变量的取值默认为 text/html。该变量还可以取值为"*",表示对所有 MIME 类型的页面数据进行 Gzip 压缩。一般情况下我们压缩常规的文件类型时,可以设置为:gzip_types text/plain application/x-javascript text/css text/html application/xml;
gzip_vary 指令
该指令用来设置在使用 Gzip 功能时是否发送带有"Vary: Accept-Encoding"头域的响应头部,该头域的主要功能是告诉接收方发送的数据经过了压缩处理。开启后的效果是在响应头部添加了 Accept-Encoding:gzip,这对于本身不支持 Gzip 压缩的客户端浏览器是有用的。语法结构为:gzip_vary on | off;
默认设置为 off。事实上,我们可以通过 Nginx 配置的 add_header 指令强制 Nginx 服务器在响应头部添加"Vary: Accept-Encoding"头域,以达到相同的效果:add_header Vary Accept-Encoding gzip;
TIP
该指令在使用过程中存在 Bug,会导致 IE4 及以上浏览器的数据缓存功能失效。
由 ngx_http_gzip_static_module 模块处理的指令
该模块是可选模块,主要负责搜索和发送经常 Gzip 功能预压缩的数据。这些数据以".gz"作为后缀名存储在服务器上。如果客户端请求的数据在之前被压缩过,并且客户端浏览器支持 Gzip 压缩,就直接返回压缩后的数据。
该模块与 ngx_http_gzip_module 模块的不同之处在于,该模块使用的是静态压缩,在 HTTP 响应头部包含 Content-Length 头域来指明报文体的长度,用于服务器可确定响应数据长度的情况;后者默认使用 Chunked 编码的动态压缩,其主要适用于服务器无法确定响应数据长度的情况,比如大文件下载的倾向,这时需要实时生成数据长度。
与该模块有关的指令主要有以下几个:gzip_static、gzip_http_version、gzip_proxied、gzip_disabled 和 gzip_vary 等。
其中的 gzip_static 指令,用于开启和关闭该模块的功能,其语法结构为:gzip static on | off | always;
- on,开启该模块的功能
- off,关闭该模块的功能
- always,一直发送 Gzip 预压缩文件,而不检查客户端浏览器是否支持 Gzip 压缩
其他指令与 ngx_http_gzip_module 模块下的使用方式相同。需要注意的是,gzip_proxied 指令只接收以下设置:gzip_proxied expired no-cache no-store private auth;
另外,对于该模块下的 gzip_vary 指令,开启以后只给未压缩的内容添加"Vary:Accept-Encoding"头域,而不是对所有内容都添加。可以通过 Nginx 配置的 add_header 指令实现。
由 ngx_http_gunzip_module 模块处理的 2 个指令
该模块是可选模块。
Nginx 服务器支持对响应输出数据流进行 Gzip 压缩,这对客户端浏览器来说,需要有能力解压和处理 Gzip 压缩数据,但如果客户端本身不支持该功能,就需要 Nginx 服务器在向其发送数据之前先将该数据解压。这些压缩数据可能来自于后端服务器压缩产生或者 Nginx 预压缩产生。
ngx_http_gunzip_module 模块便是用来针对不支持 Gzip 压缩数据处理的客户端浏览器,对压缩数据进行解压处理的,与它有关的指令主要有以下几个:gunzip、gunzip_buffers、gzip_http_version、gzip_proxied、gzip_disable 和 gzip_vary 等。
gunzip 指令
该指令用于开启或者关闭该模块的功能,语法结构为:gunzip_static on | off;
默认设置为 off 关闭功能。当功能开启时,如果客户端浏览器不支持 Gzip 处理,Nginx 服务器将返回解压后的数据,如果客户端浏览器支持 Gzip 处理,Nginx 服务器忽略该指令的设置,仍然返回压缩数据。gunzip_buffers 指令
该指令与 ngx_http_gzip_module 模块中的 gzip_buffers 指令非常类似,都是用于设置 Nginx 服务器解压 Gzip 文件使用缓存空间的大小的,语法结构为:gunzip_buffers number size;
默认设置为 off 关闭功能。当功能开启时,如果客户端浏览器不支持 Gzip 处理,Nginx 服务器将返回解压后的数据,如果客户端浏览器支持 Gzip 处理,Nginx 服务器忽略该指令的设置,仍然返回压缩数据。
gunzip_buffers number size;
- number,指定 Nginx 服务器需要向系统申请缓存空间的个数。
- size,指定每个缓存空间的大小。
根据该配置项,Nginx 服务器在对 Gzip 数据进行减压时需向系统申请 number * size 大小的空间。默认情况下 number * size 的值为 128,其中 size 的值取系统内存页一页的大小,为 4KB 或者 8KB,即:gzip_buffers 32 4K | 16 8K;
其他指令同 ngx_http_gzip_module 模块。
Gzip 压缩功能的使用
将gzip相关指令放在http全局块中,则使得Nginx服务器能够在全局范围内应用Gzip功能。如果要对各个虚拟主机差别性对待,我们可以在对应的server块中添加各自的Gzip配置指令。
Nginx 与其他服务器交互时产生的 Gzip 压缩功能相关问题
该类问题的产生原因又可以分为两类:
- 多层服务器同时开启 Gzip 压缩功能导致。
- 多层服务器之间对 Gzip 压缩功能支持能力不同导致。
问题一:如果 Nginx 和后端服务器同时开启 Gzip 压缩功能:
解决办法:对于包含多层服务器的系统来说,Nginx 服务器作为前端服务器如果开启了 Gzip 压缩,后端服务器最好就不要再开启了,否则会导致客户端浏览器再刷新过程中数据下载不完整的问题发生。
问题二:Nginx 服务器作为后端服务器和前端服务器进行交互,两类服务器对 Gzip 压缩功能的支持不同导致问题产生:
解决办法:这个要具体看场景分析,可参考《Nginx高性能Web服务器详解》第 5 章节末尾的"Nginx服务器和Squid服务器"示例说明。
参考文献
- [Nginx 高性能 Web 服务器详解]