数据库技术:一篇文章读懂nginx的gzip功能

前言http中包体【body】压缩协商对应的头字段为accept-encoding/content-encoding。对于http包体压缩,nginx的ngx_http_gzip_module模块提供

前言

http中包体【body】压缩协商对应的头字段为accept-encoding/content-encoding。对于http包体压缩,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

关于nginx gzip基本功能,其语义,逻辑,配置和使用都相当简单,网上相关文章也很多,数据库技术:一篇文章读懂nginx的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的gzip功能使用的是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    

gzip_proxied的参数解析:

  • off gzip_proxied的缺省参数是off,语义是不对代理请求的回应进行压缩。
  • any 对任意代理请求回应压缩,语义正好和off相反。
  • expired 如果回应中包含头字段expires,并且其值响应导致不会缓存,则压缩。因此可以构造缓存不过期,缓存过期2种场景,分别验证。回应中添加expires头字段可以用expires指令。
#expires 1h; #缓存有效期1小时 --->不压缩  #expires epoch;#缓存有效期设为1970年1月1日0时,即必然过期,不缓存 --->压缩  
  • no-cache no-store private 此3个参数有类似的行为和语义,放在一起说,语义是如果响应头字段包含cache-control: xxx,xxx是上述参数中的一个,则压缩。

注:响应中需要显示地携带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;  
  • no_etag 语义是如果回应中不包含头字段etag,则压缩。

etag默认打开,用etag off可以关闭。

#etag off;  
  • no_last_modified 语义是如果回应中不包含头字段last_modified,则压缩。

#未找到关闭last_modified的方法,abort。

  • auth 语义是请求中包含authorization时压缩

配置下面2条指令可以仿真基本网页认证:

#auth_basic "test for auth_basic";  #auth_basic_user_file ../src/usr;  

小结:

  1. gzip_min_length的优先级高于gzip_proxied,如果由于gzip_min_length的设置导致不压缩,则gzip_proxied即使满足压缩条件也不会压缩。
  2. 上述gzip_proxied的参数,除auth是看请求头字段,其它都是看响应头字段。
  3. off, any是一对互斥参数,表达了对代理请求是全部不压缩,或全部压缩两种相反的语义。
  4. no-cache,no-restore,priviate,no_etag,no_last_modified,都和缓存相关,表达的语义可以归纳为如果响应不缓存,则压缩,其区别只在于判断的条件的差异,当然,也可以一次性都设置上。那么为何响应不缓存就压缩呢?官方文档没有描述,博主推测和使用场景有关。
    a. 不缓存意味着不会在代理服务器上保留响应副本,那么应该尽早在消息源头压缩,减少链路上的带宽消耗。
    b. gzip是cpu密集型的使用,如果响应缓存,则可以选择在下游代理服务器上启用压缩,从而分担上游服务器的压力。

下面是具体的配置,实践实践再实践才是理解和领会相关指令和参数最有效的方法。

配置文件:

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 'okn';#如果使用return,则在gzip模块生效之前就退出,所以不会压缩。  			#content-length和cotnent-encoding不会同时出现,因为gzip是实时动态压缩,无法预先取得content-length。  			#accept-encoding实验中curl必须显示的添加accept-encoding头字段,否则视为不使用压缩方式返回响应,而浏览器天然会添加accept-encoding  			#$gzip_ratio计算的是源文件和压缩文件的大小之比,如源文件100,压缩文件20,则ratio为5  		}        }      

参考:ngx_http_gzip_module

相关文章:

总结

到此这篇关于一篇文章读懂nginx中gzip功能的文章就介绍到这了,更多相关nginx gzip功能内容请搜索<猴子技术宅>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<猴子技术宅>!

需要了解更多数据库技术:一篇文章读懂nginx的gzip功能,都可以关注数据库技术分享栏目—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/sqljc/1093028.html

(0)
上一篇 2天前
下一篇 2天前

精彩推荐

发表评论

您的电子邮箱地址不会被公开。