HTTP中包体【body】压缩协商对应的头字段为Accept-Encoding/Content-Encoding。Nginx的ngx_http_gzip_module模块支持对包体的动态gzip压缩,并有很精细的控制。
包括:
开启关闭gzip压缩: gzip on|off
对特定类型的文件进行压缩: gzip_types
设置文件大小阈值才启用压缩: gzip_min_length
设置压缩率: gzip_comp_level
查看压缩率: $gzip_ratio
是否插入Vary: Accept-Encoding头字段: gzip_vary
禁止特定浏览器使用压缩:gzip_disable
是否对代理请求响应压缩:gzip_proxied
其中gzip_proxied涉及若干参数,最为复杂,网上文章涉及不多。
本文试图通过实验把gzip,尤其是gzip_proxied,做一个全面的梳理。
gzip_proxied的基本逻辑是对于代理请求根据请求及回应决定是否压缩响应包体。判断是否是代理请求的依据是请求头中是否携带Via头字段。
如:
curl -H 'Via: 1.1 aaa' test/200_accept_encoding.css --compressed -I
响应包体是否压缩,可以curl -I查看是否有Content-Encoding: gzip
HTTP/1.1 200 OK
Server: nginx/1.20.1
Date: Fri, 18 Feb 2022 03:25:26 GMT
Content-Type: text/css
Last-Modified: Tue, 08 Feb 2022 15:48:26 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/“620290ca-3523”
Content-Encoding: gzip
压缩率可以查看log,其中5.16就是压缩率
47151 192.168.31.133 - - [18/Feb/2022:10:08:07 +0800] “GET /200_accept_encoding.css HTTP/1.1” 200 2646 “-” “curl/7.61.1” “-” 5.16
本文使用的是nginx 1.20.1, 客户端工具是curl 7.61.1, 测试文件为200_accept_encoding.css,可自行选择任意文件测试。
[root@test01 conf]# nginx -vnginx version: nginx/1.20.1[root@test01 conf]# curl -Vcurl 7.61.1 (x86_64-redhat-linux-gnu) libcurl/7.61.1 OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.6 libidn2/2.2.0 libpsl/0.20.2 (+libidn2/2.2.0) libssh/0.9.4/openssl/zlib nghttp2/1.33.0
具体细节还是看配置及说明,实践实践再实践才是理解和领会相关指令和参数最有效的方法。
配置文件:
log_format gzip '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" $gzip_ratio';server { listen 80; server_name test test1; root html; access_log logs/200_accept_encoding_access.log gzip; error_log logs/200_accept_encoding_error.log debug; default_type text/plain; #gzip off; #gzip *可以表示所有文件类型 gzip_types application/javascript application/x-javascript text/css *; #mp4有专属的mime类型,video/mp4,而不是application/octet-stream,可以在conf/mime.types中查看详细的mime类型。 #gzip_types application/javascript application/x-javascript text/css application/octet-stream; #gzip_types application/javascript application/x-javascript text/css video/mp4; gzip_vary on;#控制是否插入Vary: Accept-Encoding头字段。 gzip_comp_level 6;#设置压缩级别,缺省为1,可以不用改,级别6大约和gzip命令行缺省压缩率相当 gzip_min_length 13603;#设定最小待压缩的文件大小,大小的依据是Content-Length,使用的测试文件为200_accept_encoding.css,大小正好是13603。 #gzip_disable "(Chrome|curl|Firefox)";#根据User-Agent的返回值,针对特定客户端禁止压缩 #gzip_proxied off;#设置是否压缩代理请求的回应,代理请求依据请求头中是否包含Via字段,off表示只要请求头中包含Via字段,则不压缩 #gzip_proxied expired;#如果回应中包含头字段Expires,并且其值导致不会缓存,则压缩。注:该设置不考虑是否在请求中包含Via #回应中添加Expires头字段,注:使用expires会同时添加Expires和Cache-Control头字段 #expires 1h; #缓存有效期1小时 #expires epoch;#缓存有效期设为1970年1月1日0时,即回应包体必然过期,不缓存 #gzip_proxied no-cache no-store private有类似的逻辑,如果响应头字段包含Cache-Control: xxx,则压缩 #有2点需要注意,1.受Via字段影响;2.回应中需要显示包含Cache-Control头字段,如果不包含则压缩 #gzip_proxied no-cache; #gzip_proxied no-store; gzip_proxied private; #回应添加Cache-Control用add_header #add_header Cache-Control no-store; #add_header Cache-Control no-cache; #gzip_proxied no_etag;#如果回应中不包含头字段ETag,则压缩。注:该设置考虑是否在请求中包含Via #etag off; #curl可以使用2种命令行方式验证gzip,一种是添加Accept-Encoding头字段,一种使用compressed参数 #curl -H 'Accept-Encoding: gzip' test/200_accept_encoding.css --output a.css #curl test/200_accept_encoding.css --compressed #如果客户端请求不支持的压缩方式如br,则服务器将忽略之 location / { #return 200 'okn';#如果使用return,则在gzip模块生效之前就退出,所以不会压缩。 #Content-Length和Cotnent-Encoding是一对互斥的头字段,它们不会同时出现。 #Accept-Encoding实验中curl必须显示的添加Accept-Encoding头字段,否则视为不使用压缩方式返回响应,而浏览器天然会添加Accept -Encoding #$gzip_ratio计算的是源文件和压缩文件的大小之比,如源文件100,压缩文件20,则ratio为5 } }
参考:ngx_http_gzip_module