請求壓縮,是將伺服器的結果透過 Nginx 將內容壓縮後,在傳送給客戶端,降低網路傳輸壓力,提升傳輸效率。
常見的兩種請求方式是: gzip 、brotli(Google),相當於 brotli 的效率會高,後續內容詳解。
請求壓縮的話分為:動態壓縮,靜態壓縮,動態壓縮會導致 Nginx內部的 sendfile 失效。對於一些不變的內容可以使用靜態壓縮,提升請求效率 。
用於請求結果的壓縮,需要客戶端和伺服器雙方支援壓縮協議,在伺服器進行結果的壓縮,客戶端進行資料解壓縮,在壓縮會佔用伺服器端一些效能效率,這個損耗根據壓縮的等級來定,等級越高,耗損越大。可以減少網路傳輸壓力。
壓縮只針對於 代理方式請求才會生效。
執行的流程是:客戶端向伺服器端發送請求,nginx 接收請求之後,會向上游伺服器伺服器發送請求,Nginx和上游伺服器之間會創建網路通道,之間會進行資料的傳輸,在這裡如果是開啟了壓縮操作,那麼Nginx會將結果資料進行壓後,在將資料傳回給客戶端,在瀏覽器接收到nginx的請求,會先處理請求頭,發現有壓縮協議,那麼就會判斷當前瀏覽器是否支援該協議,如果支援則會將數進行解壓的操作並資料展示給使用者。
開啟壓縮之後用戶是無感的,可以降低傳輸壓力,但是圖片和影片就不建議壓縮了,因為後的大小變化不大,gzip是網路傳輸的壓縮的,需要客戶端支持,伺服器端也需要支持,將傳輸的資料進行壓縮,將傳輸資料變小,我們可以設定下,當然壓縮必越高,解壓縮和壓縮的時間更長,伺服器端壓力會大些。
Gzip是GNUzip的縮寫,最早用於UNIX系統的檔案壓縮。 HTTP協定上的Gzip編碼是一種用來改善Web應用程式效能的技術,Web伺服器和客戶端(瀏覽器)必須共同支援Gzip。目前主流瀏覽器:Chrome、Firefox等都支援該協議,常見的伺服器:Apache、Nginx、IIS同樣支援Gzip。
Gzip的壓縮比率約為3-10倍(純文字),可以大幅節省伺服器的網路頻寬。在實際應用中,並不是對所有檔案進行壓縮,通常只壓縮靜態檔案(js\css\html)。 JPEG這類檔案用Gzip壓縮的不夠好,而且壓縮也是耗費CPU資源的。
那麼Gzip是如何進行壓縮的呢?簡單來說,Gzip壓縮是在一個文字檔案中找出類似的字串,並臨時替換他們,使整個檔案變小。這種形式的壓縮對Web來說非常合適,因為HTML和CSS檔案通常包含大量的重複字串,例如空格、標籤等。
gzip模組是由Nginx內建的,所以不需要添加其他的默認,只要配置安裝好Nginx既可。
使用作用域:http , server , location
Nginx 如下設定
gzip on ;
是否開啟壓縮。
預設值:gzip off預設關閉
gzip_buffers 32 4k | 16 8k
#壓縮緩衝區大小。
預設值: gzip_buffers 32 4k | 16 8k
gzip_comp_level 1 ;
壓縮等級1-9 ,數字越大壓縮比越高。
越小壓縮速度和解壓縮速度越快,壓縮佔比越小
預設值:gzip_comp_leve 1
#gzip_http_version 1.1
使用gzip 的最小的http版本。
gzip_min_length
#設定將被 gzip 壓縮的回應的最小長度。長度僅由 "Content-Length" 回應標頭欄位決定。
gzip_proxied 多重選擇
#對於上游伺服器傳回不同的head來決定是不是要進行壓縮,兩種常見的一種off一種any
#########一般啟用cache的話都是所有已經進行過壓縮的可以規避一些細節############off 為不做限制。 ############當反向代理時,針對於上游伺服器傳回的頭資訊進行壓縮。 ############expired - 啟用壓縮,如果header頭中包含"Expires" 頭資訊############no-cache - 啟用壓縮,如果header頭中包含"Cache-Control:no-cache" 頭資訊############no-store - 啟用壓縮,如果header頭中包含"Cache-Control:no-store" 頭資訊###private - 啟用壓縮,如果header頭中包含"Cache-Control:private" 頭資訊
no_last_modified - 啟用壓縮,如果header頭中不包含"Last-Modified" 頭資訊
no_etag - 啟用壓縮,如果header頭中不包含"ETag" 頭資訊
auth -啟用壓縮, 如果header頭中包含"Authorization" 頭資訊
any - 無條件啟用壓縮。
gzip_vary on ;
#增加一個header ,適應舊的瀏覽器Vary : Accept-Encoding
#gzip_types :
哪些mime類型的檔案進行壓縮。
gzip_disable :
#禁止哪些瀏覽器使用gzip。
建議不要設定
預設值: gzip_disable 'msie6MSIE [4-6]\.MSIE 6.0'
location / { gzip off ; # 开启gzip压缩 gzip_buffers 32 4k ; # 设置缓冲区大小 gzip_comp_level 5; # 设置压缩等级 1-9 gzip_disable 'msie6MSIE [4-6]\.MSIE 6.0'; # 禁止哪些浏览器不使用压缩 gzip_http_version 1.1; # 设置压缩所需要的最低的http版本。 gzip_min_length 20 ; # 设置响应的数据最小限制,在这个限制之后再回进行压缩 gzip_vary on ; # 增加一个header ,适用于老的浏览器 Vary:Accept-Encoding gzip_proxied any; # 无条件启动压缩 # 哪些mime类型的文件进行压缩 #gzip_types text/plain application/x-javascript text/css application/xml; gzip_types text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml text/javascript application/javascript application/x-javascript text/x-json application/json application/x-web-app-manifest+json text/css text/plain text/x-component font/opentype application/x-font-ttf application/vnd.ms-fontobject image/x-icon; }
當啟動了gzip,我們的請求到nginx伺服器上,nginx就已經給我們生產了response heard 但是資料還沒有生成,他也不知道具體數據有多大,因為nginx是異步響應式請求,他一步一步來的,他先把header準備好然後請求內容去壓縮,最後將兩塊內容合併去壓縮,最後發過來,也就是因為非同步導致他不知道具體大小。
他是先將請求頭回傳然後資料在慢慢讀取。
----------------------------------响应体------------------------------------------------- Connection: keep-alive Content-Encoding: gzip # 结果启动了gzip压缩 Content-Type: application/json # 响应结果 Date: Mon, 13 Feb 2023 09:13:19 GMT Keep-Alive: timeout=65 Server: nginx/1.20.2 Transfer-Encoding: chunked # 传输的格式这个对应的就是length,这个是他会发送一个一个的包,当最后一个包是0表示传输结束 Vary: Accept-Encoding ------------------------------------请求头----------------------------------------------- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cache-Control: max-age=0 Connection: keep-alive Host: 192.168.101.128 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
注意:以上是動態壓縮就是所有的請求都會經歷一次壓縮,這個有一個致命的缺點就是不支援sendfile,sendfile是資料零拷貝,不會將資料載入到nginx,而是透過網路介面傳遞數據,但是一旦開啟了gzip動態壓縮會導致sendfile失效,可以使用靜態壓縮。
在多層 Nginx時,建議和伺服器建立連線的Nginx進行開啟Gzip 就可以了,這樣就會支援gzip,在任一台開啟都是會開啟的gzip的 。
為什麼要使用靜態壓縮呢?
首先動態壓縮無法使用 sendfile 而靜態壓縮則完美的解決了這個問題。
靜態壓縮是一個互補或是說是一個擴展的功能,他可以把請求的這些資源文件,我們可以預先的將內容進行壓縮成一個壓縮包。
首先靜態的資源一定是要比動態的資源要效率高,通過壓縮之後可以減少磁碟的大小,並且還可以節省網路的通道資源。
什麼是靜態壓縮
靜態壓縮不適合反向代理只適合資源伺服器,他可以把壓縮的檔案傳遞給客戶端,靜態壓縮就是在資源路徑下會有一個資源檔案還會有一個對應名稱的壓縮包。而Nginx會優先找壓縮包,直接透過 sendfile 將資料傳遞過去。
Nginx 將壓縮的文件透過網路傳送過去,然後當瀏覽器接收到Nginx發送的壓縮包文件,並進行解壓縮的操作。他會在發送給客戶端之前將壓縮包介面在發送給客戶端。
3. 配置
該http_gzip_static_module模組允許發送帶有「」檔案副檔名的預壓縮文件,.gz而不是常規檔案。預設不建置此模組,應使用 --with-http_gzip_static_module 配置參數啟用它。這個模組沒有在預先編譯的包裡,需要手動添加,這個模組的作用就是把壓縮包解開壓縮開
#with是內部模組,add是外部的模組。
第一次安裝nginx時使用
./configure --prefix==/usr/local/nginx --with-hhtp_gzip_static_module
make && make install
已經安裝過nginx,對nginx客戶端升級時使用指令
./configure --prefinx==/usr/local/nginx --with-http_gzip_static_module
make不要make install 否則會覆寫先前的文件
在將objs的nginx 程式拷貝到/usr/local/nginx/sbin 下·,注意需要做好原nginx 程式備份。
語法 : gzip_static on | off | always;
作用:是否開啟靜態壓縮功能。
參數值:
on :開啟靜態壓縮,並會偵測瀏覽器是否支持,如果不支持則不會走靜態壓縮,
off :關閉靜態壓縮
always:是否使用靜態壓縮,無論瀏覽器是否支援靜態壓縮功能。
這樣就會引發一個問題,如果客戶端不支持,就解不開,如果磁碟上沒有未壓縮的檔案預設會報404,可以配合ngx_http_gunzip_module ,模組使用。
預設值:gzip_static on
#適用於 :http、server、location
使用的需要将本地的资源文件进行压缩 ,压缩成 xxx.gz的文件
cd /usr/local/nginx/html gzip *
注意:开启之后默认就会先访问 .gz 的文件了,如果不支持 静态压缩则会访问 正常文件,如果没有正常的文件只有 .gz 那么就会报错 。
4. nginx_http_gunzip_module 模块
这个模块是配合 gzip_static always时使用的 ,因为 当配置程 always 时,所有的请求会都进行找压缩文件,在文件存不存在或者说浏览器支不支持 静态压缩,nginx都会将静态压缩文件返回给浏览器,如果浏览器不支持的话会导致文件解不开,也就是 404 。
这个模块它没有在预编译的包里,需要手动添加,这个模块的作用就是把静态的压缩包解压开,他会在发送给客户端之前将压缩包接口在发送给客户端,它相当于是一层拦截器,它的作用就是可以把源文件进行压缩,我们可以把源文件进行删除了,节省磁盘空间,但是一般会用到。
注意 : with 是内部 、 add 是外部的
安装命令 :
./configure --prefix=/usr/local/nginx --add-module=/tools/nginx-sticky --with-http_gzip_static_module --with-http_gunzip_module
make
如果是替换的话,则将这个文件中的这个文件 cp 到 nginx的安装目录下的 sbin
移动命令:
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old2 cd /tools/nginx/objs mv nginx /usr/local/nginx/sbin/
这里没有gzip,但也没有 context-length 因为nginx需要把文件解压缩,他也不知道具体文件有多大,这个 gzip_static 适用场景 :在作为cdn服务器或者 cdn上游服务器文件存储服务器时,我们就可以把本地原始文件删了,只展示zip 包,把解压缩的压力丢弃给客户端 , 同时可以把本地压缩等级,提高不是 gzip的压缩等级 ,经常高配访问的一些页面 css js ,也可以通过 static压缩。
静态压缩 响应结果会有 Context-Encoding : gzip 、Conten-Length:392 有展示 context-length 表示他开启了静态压缩,预压缩直接返回zip包 没有源文件 ,1.速度快,2节省服务器资源。
Brotli 是 Google 推出的开源压缩算法,通过变种的 LZ77 算法、Huffman 编码以及二阶文本建模等方式进行数据压缩,与其他压缩算法相比,它有着更高的压缩效率,性能也比我们目前常见的 Gzip 高17-25%,可以帮我们更高效的压缩网页中的各类文件大小及脚本,从而提高加载速度,提升网页浏览体验。需要说明的是 Brotli 压缩只在 https 下生效,因为 在 http 请求中 request header 里的 Accept-Encoding: gzip, deflate 是没有 br 的。
Brotli 如此高的压缩比率,得益于其使用一个预定义的字典,该字典包含超过 13000 个来自文本和 HTML 文档的大型语料库的常用字符串,预定义的算法可以提升较小文件的压缩密度,而压缩与解压缩速度则大致不变。
Brotli 凭借它优异的压缩性能迅速占领了市场,从下图可以看到,除了 IE 和 Opera Mini 之外,几乎所有的主流浏览器都已支持 Brotli 算法,因此处于资源占用的考虑,比如说流量,建议启用:
Brotil 规范由 Google 员工 Jyrki Alakuijala 和 Zoltan Szabadka 于 2013-2016开发,并伴随着规范的俩个作者Evgenii Kuliuchniko 和 Lode Vandevenne共同开发的参考实现,后者之前开发了谷歌的zopfli在2013年重新实现了收缩 /gzip 压缩格式。与zopfli不同,后者是对现有数据格式规范的重新实现,Brotli 是一种新的数据格式,并允许作者进一步提高压缩比。
Brotli 的编码器提供了 12 个质量级别 (从 0 到 11)。它们是压缩速度换取压缩效率的压缩模式:更高质量的几倍速度较慢,但会产生更好的压缩比。
一个 Brotli 压缩文件由 元块(meta-blocks)集合组成。每个元块最多可容纳 16 MiB,由俩部分组成:一个 数据部分(data part),它存储 LZ77 压缩的放入快,以及一个 标题(header),每个块的压缩遵循经典的 ①LZ77 压缩方案并由 ②计算具有良好的LZ77解析和计算 LZ 短语的简洁编码这俩个主要阶段组成。
它效率高是因为内置了 n多个字典,包含都是一些常见的文件文件 css 、js 等等一些标签,如果我们将这些标签归类生成一个字典之后,我们就可以按照序号去解压这个文件了。
并且它在 Nginx 中话是可以和 Gzip 共存,开启了Brotli 不会导致 Gzip失效,如果浏览器支持brotli 那么优先使用 Brotli ,不支持在使用 Gzip。
--add-dynamic-module表示动态的引入模块在配置文件中还需要单独加入 load_module path/xxx
官网
https://github.com/google/ngx_brotli
https://codeload.github.com/google/brotli/tar.gz/refs/tags/v1.0.9
下载 俩个项目
解压缩
brotli-1.0.9 是 brotli 算法模块,需要先解压。
tar -zxvf brotli-1.0.9.tar.gz
ngx_brotli-1.0.0rc 是nginx的 brotli的模块。这模块里需要引入 brotli 算法模块
tar -zxvf ngx_brotli-1.0.0rc.tar.gz
接下来讲 brotli 的内容全部 复制到 ngx_brotli 的 deps/brotli/目录
cd /tools/brotli-1.0.9
cp -r * /tools/ngx_brotli-1.0.0rc/deps/brotli/
模块化编译 :
./configure --with-compat --add-dynamic-module=/tools/ngx_brotli-1.0.0rc --prefix=/usr/local/nginx/
或
--add-dynamic-module=brotli目录
加载所有的压缩模块
./configure --with-compat --add-dynamic-module=/tools/ngx_brotli-1.0.0rc --prefix=/usr/local/nginx/ --add-module=/tools/nginx-sticky --with-http_gzip_static_module --with-http_gunzip_module
make && make install
下载的两个模块 拷贝到 /usr/local/nginx/modules/
首先在 /usr/local/nginx创建一个modules文件夹 mkdir modules
mv ngx_http_brotli_filter_module.so ngx_http_brotli_static_module.so /usr/local/nginx/modules/
最后将新编译的 nginx 启动程序复制到 /usr/local/nginx/sbin下 做好之前程序复制。
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.oid3
mv /tools/nginx-12.0/objs/nginx /usr/local/nginx/sbin/
在配置文件中动态加载模块
load_module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so"; load_module "/usr/local/nginx/modules/ngx_http_brotli_static_module.so";
具体的配置选项可以查看GitHub: https://github.com/google/ngx_brotli
brotli的配置可以参考Gzip的配置,几乎一致。
brotli
语法:brotli on | off
默认值 :brotli off
适用于: http、server、location、if
作用:开启或者禁用brotli 压缩功能。
brotli_static
语法:brotli_static on | off | always
默认值:brotli_static off
适用于:http、server、location
作用:brotli 也是支持预先压缩文件,启用或禁用检查是否存在带扩展名的预压缩文件.br 。使用该always值,在所有情况下都使用预压缩文件,而不检查客户端是否支持它。
brotli_types
语法:brotli_types
默认值:brotli_types text/html
适用于: http、server、location
作用:指定哪些资源类型需要进行压缩操作,特殊值*匹配任何 MIME类型。
brotli_buffers
语法:brotli_buffers
默认值: 32 4k | 16 8 k
适用于: http、server、location
作用:设置压缩缓冲区大小,最新版本以及弃用了 。
brotli_comp_level
语法:brotli_comp_level
默认值 :6'
适用于 : http、server、location
作用 : 设置即时压缩 Brotli 质量(压缩)level。0可接受的值在从到 的范围内11。
brotli_window
语法:brotli_window
默认值 : 512k
适用于 :http、server、 location
作用:设置 Brotli 窗口size。可以比作是一个桌子,将要压缩的文件同时放在这个桌子上,这个桌子上可以放多少文件的大小,这个值也不越大越好,他比较占内存,值增加建议是2的倍数,可接受的值为1k, 2k, 4k, 8k, 16k, 32k, 64k, 128k, 256k, 512k, 1m, 2m,和4m。8m 16m
brotli_min_length
语法:brotli_min_length
默认值:20
适用于: http、server、location
作用:指定进行压缩的文件最小的长度,如果小于这个值则不压缩。
#加载动态模块 load_module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so"; load_module "/usr/local/nginx/modules/ngx_http_brotli_static_module.so"; worker_processes 1; events { worker_connections 1024; } http { server { listen 80; server_name localhost; location / { #brotli配置 brotli on; # 开启 压缩 brotli_static on; # 是否开启预先压缩,开启之后就会 .br的压缩包 brotli_comp_level 6; # 压缩等级 brotli_buffers 16 8k; # 缓冲区大小 ,已经启用 brotli_min_length 20; # 压缩时文件最小限制 # 对哪些mime.types类型进行压缩 brotli_types text/plain text/css text/javascript application/javascript text/xml application/xml application/xml+rss application/json image/jpeg image/gif image/png; } } }
因为默认 brotli 是必现 https 请求才能使用的,因为 http的请求 请求头的 Accept-Encoding 是没有 br的,所以服务器是无法知道客户端可以使用的。
测试方案:
使用 linux 的 curl 命令 :
curl -H 'Accept-Encding : br' -I 192.168.101.128/index.html
[root@localhost sbin]# curl -H Accept-Encoding:br -I http://192.168.101.128/static_page.html HTTP/1.1 200 OK Server: nginx/1.20.2 Date: Fri, 17 Feb 2023 08:11:05 GMT Content-Type: text/html Last-Modified: Fri, 17 Feb 2023 03:28:14 GMT Connection: keep-alive Keep-Alive: timeout=65 Vary: Accept-Encoding ETag: W/"63eef44e-31" Content-Encoding: br [root@localhost sbin]# curl -I http://192.168.101.128/static_page.html HTTP/1.1 200 OK Server: nginx/1.20.2 Date: Fri, 17 Feb 2023 08:11:54 GMT Content-Type: text/html Last-Modified: Fri, 17 Feb 2023 03:28:14 GMT Connection: keep-alive Keep-Alive: timeout=65 Vary: Accept-Encoding ETag: W/"63eef44e-31"
以上是Nginx請求壓縮如何實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!