首页  /  Nginx 进阶  /  正文

Nginx 的 Gzip 动态与静态压缩

Nginx 进阶 2026-10-02📖 15 分钟👁 —
🚀 Nginx 水平扩展与优化第 6 / 8 页12345678📖 完整导航 →

Gzip

Gzip 动态压缩及缺点

网站的 gzip 压缩介绍

客户机和服务器在 HTTP 协议上添加 request 的 header accept-encoding: gzip。

可以设置压缩等级,类似于 rar 和 zip 的压缩,等级越高文件越小。

解压缩对 cpu 的消耗对服务器很明显对客户端不明显,一般构建网站会配置 gzip 的。

随便找一个大网站,控制台看 200 响应码的数据包(不看 301 重定向)。

京东首页的资源列表,请求头里 Accept-Encoding 是 gzip, deflate, br, zstd

google 自己开发了 br 压缩算法,客户端 chrome 肯定支持,国内的基本都支持,国内好多都是基于 chrome 开发的。

参数配置

gzip on;
gzip_buffers 16 8k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_min_length 1024;
gzip_proxied any;

此配置的参数如图,其中 off 和 any 是比较常见的。

gzip_proxied 各个可选值的含义,off、expired、no-cache、any 等

可以看到只对反向代理服务器生效,而且是针对上游服务器返回的 header。

gzip_vary on;
gzip_types text/plain text/css application/javascript application/json application/xml text/javascript;
gzip_types 默认覆盖的 MIME 类型列表

如图,建议多配置,因为少配了就不压缩的。

gzip_disable "MSIE [1-6]\.(?!.*SV1)";

不建议配置,有正则,会极大消耗性能,越复杂的正则越影响性能。

在 /etc/nginx/nginx.conf 配置 gzip 全局生效后重启 nginx:

gzip on;

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 256;
# 其中好多都是nginx默认自带的,直接删去注释即可
# 配置参数的具体意思不用纠结

配置gzip前后test页面的控制台对比图

响应头里 gzip 前后的对比,上面是压缩后的,下面是没压缩的

其中 transfer-encoding chunked 表示数据包拆成小块发送,最后发送的包为 0 字节表示所有的数据传输完毕,是 gzip 启用的标志。

显示 Content-Encoding: gzip 就认为 content-length 配置生效。

gzip_vary on; 一般是给老的浏览器配置的,只是多了一个字段而已。

控制台有一个 wifi 的图标,可以查看当前浏览器支持的压缩算法:

测试服务页的控制台,红箭头从 wifi 图标指向右侧的“网络条件”面板,红框里是已接受的 Content-Encoding:deflate、gzip、br、zstd

zstd 也是很好的算法只是老的浏览器不支持。

这里还有好多测试用的功能:

网络条件面板里的网络限速和 Content-Encoding 选项

以上是动态压缩,请求到后端都会压缩,致命缺点就是无法使用 nginx 的高级特性 sendfile(针对本地磁盘文件,数据零拷贝,直接与内核交流找文件,不加载到 nginx 内存,直接通过网卡驱动传数据)。

但是还是期望使用 Gzip,且不放弃 sendfile,就需要静态 Gzip 压缩。

Gzip 静态压缩及扩展配置

编译安装

静态是动态的扩展功能,可以预先打包压缩包。

nginx 开启了静态压缩会优先读取 gz 文件。

在官方文档可以找到 gz 的相关配置。

官方文档左侧的模块列表,框出了 gzip 和 gzip static 两个模块

可以看到静态 Gzip 配置说明了,不默认在预编译的包里,要手动加入。

gzip_static 模块文档页的开头,红框标出 not built by default 和 --with-http_gzip_static_module 编译参数

但是默认安装的 nginx 是带有静态 Gzip 功能的。

nginx -V(大写) 可以看到版本和编译时配置的信息。

其中有 --with-http_gzip_static_module

编译过程

cd nginx-1.21.6                    # 进入 Nginx 源码目录,必须在源码目录安装
ls                                  # 看看里面有什么
./configure --prefix=/usr/local/nginx --with-http_gzip_static_module   # 配置编译选项,指定安装路径,开启 gzip 静态模块
make                                # 编译(不安装)
systemctl stop nginx               # 停掉旧 Nginx
cd objs/                            # 进入编译输出目录
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old1   # 备份旧的可执行文件
cp nginx /usr/local/nginx/sbin/     # 把新编译的 nginx 替换过去

这是源码编译升级 Nginx 的流程,用新编译的 nginx 可执行文件替换旧的,然后重启就能用新功能。

其中 ./configure 是编译前的配置检查脚本。

配置选项说明

直接查看官方的文档:

gzip_static 文档的 Example Configuration 和 Directives(Syntax、Default、Context),以及 always 说明里的 ngx_http_gunzip_module 链接

中间的 Directives(命令)标题就是可配置的参数,只有 3 个配置选项。

gzip_static on/off/always; 作用域依然是 server、location、http 三个,也就是把它配置到和动态 Gzip 一个地方即可。

gunzip 模块文档的 Example Configuration,以及 gunzip、gunzip_buffers 的语法和默认值

本机上有原文件和压缩包,有了这个之后可以把原文件都删掉,假设之前有 2w 个文件和 2w 个压缩包,用了 gunzip 就可以删掉原文件,无需读取原文件(因为支持 Gzip 的客户端需要保留压缩包,不支持的又配合 gunzip 变成也只需要压缩包,所以可以删除原文件)。

主要功能就是节约了磁盘空间。

虽然听起来很牛但是仅仅只是在特殊场景下才行,大多数都不去配置这个。

同样 --with-http_gunzip_module 模块是 gunzip 功能的编译模块,默认安装的 nginx 同样配置在 nginx.conf。

--with-http_gunzip_module 也在默认安装的编译模块中。

        #动态Gzip配置
        gzip on;

        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_min_length 1024;

        #静态Gzip配置及其扩展配置
        gzip_static always;
        gunzip on;
        gunzip_buffers 32 4k;

gunzip on; 和 gzip_static on; 其实是冲突的,静态压缩指定了,先找压缩文件,然后找源文件,没有指定必须发送压缩文件,可以改为 always,即必须发送压缩包,此时配合 gunzip 一同配置才会生效。

这个请求的响应头里只有 Transfer-Encoding: chunked,没有 Content-Length

此种方式无法得知文件的大小,即 content-length,因为传回的是解压后的文件,磁盘上只剩压缩包了自然无法返回文件的大小(服务器端帮客户端解压)。

由于返回的是后端的文件,所以如果做了动静分离就不需要请求后端文件,无法测试 gunzip 的功能了。

创建测试文件

mkdir -p /var/www/html/testgunzip
echo "gunzip works" | gzip > /var/www/html/testgunzip/index.html.gz
# 文件是root创建的,有root权限普通用户无法读取,需要修改一下
sudo chown -R www-data:www-data /var/www/html/testgunzip
sudo chmod -R 755 /var/www/html/testgunzip

# 然后在default下配置location块
location /testgunzip {

}
访问 testgunzip 页面,浏览器上显示 gunzip works

之后删除了测试文件,符合规范。

当 nginx 直接作为 CDN 存储数据服务器的时候可以只开静态的 gzip,本地原文件可以删除,把解压缩的压力丢给客户端。一些高频访问的页面也可以用 static 压缩,可以把 static 看作是动态的一种扩展(不建议对二进制、音频、视频做 gzip 压缩,因为本来就是“压缩”的形式了)。

访问一个网站,看他控制台同时有 gzip 和 content-length 就说明他用了静态 gzip。

因为动态压缩边压边发不知道总文件大小,静态才知道(一些大网站的会这样配置,好处就是加载快),当然一些文本文件适合,但是不是所有文件类型,配置方式就是把 /var/www/ 下的网站资源全都搞成压缩包的形式:

html 目录下只剩 401.html.gz、50x.html.gz、index.html.gz 这些压缩包,原文件已经删掉

这样修改的时候需要解压缩很麻烦,所以可以这样:

进入当前目录 gunzip -r ./ 直接回来了都。

为了避免 sendfile 失效需要去配置静态的 gzip(一般权限都在架构师和项目总监上)。

Brotli

安装(太耗时了且需求不大,不演示了直接贴图)

brotli 是谷歌原创的,很多站点都会使用,默认是 https 协议,之后也支持了 http。

算法的效率很高,因为其中字典很多,对文本文档效率显著。此配置是可以和原有的 gzip 配置共存,也可以看作是一个扩展。浏览器一般优先 brotli 后使用 gzip。

由于编译方式不适用于我的 nginx 此处仅用视频实操做演示。

brotli 模块的编译步骤,下载源码、动态模块编译、配置 load_module
brotli 官方文档里的 brotli_static、brotli、brotli_types、brotli_buffers 的语法和默认值

brotli 不能和 gunzip 共存,可以注释掉 gunzip。

使用参数

配置和 gzip 基本是一样的。

官方文档:https://github.com/google/ngx_brotli

brotli_comp_level、brotli_window、brotli_min_length 的语法和默认值
brotli on;
    brotli_static on;
    brotli_comp_level 6;
    brotli_buffers 16 8k;
    brotli_min_length 20;
    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_static on | off | always; 同样支持预先压缩,变成 .br 文件,先找压缩包后找原始文件。

brotli on | off

brotli_types 对文档类的 css,js,html 效果显著,视频图片不建议。

brotli_comp_level 压缩等级。

brotli_window 512k; 窗口值,压缩软件通用的概念,压缩一份数据先准备一个地方放进去然后压缩,影响速率。

brotli_min_length 最小的压缩内容长度。

其余的配置基本用不到了。

具体配置

依旧配置在 nginx.conf。

nginx.conf 的 location 里 gzip 和 brotli 两段配置放在一起
curl 带 accept-encoding:br 请求,响应头里出现 Content-Encoding: br