时间:2023-01-18 11:01:11 | 栏目:Nginx | 点击:次
HTTP中包体【body】压缩协商对应的头字段为Accept-Encoding/Content-Encoding。对于HTTP包体压缩,Nginx的ngx_http_gzip_module模块提供了动态gzip压缩功能,并且有很精细的控制。
包括:
关于Nginx gzip基本功能,其语义,逻辑,配置和使用都相当简单,网上相关文章也很多,本文不再赘述,具体细节可以参看下文的配置实例及说明。本文将重点讨论其中的gzip_proxied指令的语义和使用,其涉及若干个参数,特定的应用场景,最为复杂,且网上文章涉及不多。
gzip_proxied的基本逻辑是对于代理请求,根据请求及回应的头字段决定是否压缩响应包体。判断的依据是请求头中是否携带Via头字段。
如:
对应的典型网络拓扑如下:
client — proxy1 — proxy2 — … proxyn — reverse proxy — origin web
我们的配置点在reverse proxy上, 也就是企业提供对外WEB服务的边缘的反向代理服务器。通常,proxyx会通过Via头字段标记消息自己的版本号和名称,从而形成了一条有序的消息路径,方便排错。
这是一个取自京东首页的Via字段的值,表示博主访问京东首页中间经过了2台代理服务器。
Via: http/1.1 ORI-CLOUD-HEN-MIX-109 (jcs [cSsSfU]), http/1.1 HENzhengzhou-CT-1-MIX-34 (jcs [cRs f ])
我们可以通过在curl中添加头字段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
tail -f ../logs/200_accept_encoding_access.log 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
其中5.16就是压缩率
本文使用的是nginx 1.20.1, 客户端工具是curl 7.61.1, 测试文件为200_accept_encoding.css,可自行选择任意文件测试。
[root@test01 conf]# nginx -v nginx version: nginx/1.20.1 [root@test01 conf]# curl -V curl 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
#expires 1h; #缓存有效期1小时 --->不压缩 #expires epoch;#缓存有效期设为1970年1月1日0时,即必然过期,不缓存 --->压缩
注:响应中需要显示地携带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; #add_header Cache-Control private;
可以同时设置多个gzip_proxied条件:
#gzip_proxied no-cache no-store private;
add_header也可以为Cache-Control设置多个值,对于这种有冲突的Cache-Control设置,以最严格的限制为准,如本例是no-store生效。
#add_header Cache-Control no-store,no-cache,private;
ETag默认打开,用etag off可以关闭。
#etag off;
#未找到关闭last_modified的方法,abort。
配置下面2条指令可以仿真基本网页认证:
#auth_basic "test for auth_basic"; #auth_basic_user_file ../src/usr;
下面是具体的配置,实践实践再实践才是理解和领会相关指令和参数最有效的方法。
配置文件:
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;#这是设置为off,原因是我在http级别已经把gzip打开了。 gzip_buffers 16 8k;# gzip_buffers number size; gzip_comp_level 6;#设置压缩级别,缺省为1,可以不用改,级别6大约和gzip命令行缺省压缩率相当。 #gzip_disable "(Chrome|curl|Firefox)";#根据User-Agent的返回值,针对特定客户端禁止压缩。这里把3种客户端都禁了。 #Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 #curl/7.61.1 #Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0 #gzip_http_version 1.1;#指定gzip压缩针对的HTTP版本 #gzip_min_length 13603;#设定最小待压缩的文件大小,大小的依据是Content-Length,使用的测试文件为200_accept_encoding.css gzip_min_length 620;#index.html文件大小正好是620 #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_proxied off;#设置是否压缩代理请求的回应,代理请求的依据是请求头中是否包含Via字段,off表示只要请求头中包含Via字段,则不压缩。 #gzip_proxied expired;#如果回应中包含头字段Expires,并且其值导致不会缓存,则压缩。 #注1:该设置不考虑是否在请求中包含Via #注2:注1理解是错误的,进入gzip_proxied的先决条件一定是头字段中包含Via字段,以当前的设置,在不考虑gzip_proxied影响的情况下,响应一定是压缩的,所以给人以误解,当gzip_proxied条件满足时无论是否有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; #add_header Cache-Control private; #可以同时设置多个gzip_proxied条件: #gzip_proxied no-cache no-store private; #add_header也可以为Cache-Control设置多个值,对于这种有冲突的Cache-Control设置,以最严格的限制为准。 #add_header Cache-Control no-store,no-cache,private; #gzip_proxied no_etag;#如果回应中不包含头字段ETag,则压缩。 #etag off; #未找到关闭last_modified的方法,abort #gzip_proxied no_last_modified; #if_modified_since off; #gzip_proxied any;#对任意代理请求回应压缩。 gzip_proxied auth;#请求中包含Authorization时压缩 auth_basic "test for auth_basic"; auth_basic_user_file ../src/usr; #curl -H 'Via: 1.1 aaa' test --compressed --basic -u root:root #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 'ok\n';#如果使用return,则在gzip模块生效之前就退出,所以不会压缩。 #Content-Length和Cotnent-Encoding不会同时出现,因为gzip是实时动态压缩,无法预先取得Content-Length。 #Accept-Encoding实验中curl必须显示的添加Accept-Encoding头字段,否则视为不使用压缩方式返回响应,而浏览器天然会添加Accept-Encoding #$gzip_ratio计算的是源文件和压缩文件的大小之比,如源文件100,压缩文件20,则ratio为5 } }