NGINX开启zstd压缩

Meta 的 Yann Collet 刚刚发布了 Zstd 1.5.6,这是 Zstandard 压缩实现的最新版本。此次发布的部分原因是 Google Chrome 浏览器添加了对网络流量 Zstd 编码的支持。Chrome 浏览器现在允许使用 Zstandard (zstd) 作为内容编码,以加快页面加载速度并节省带宽。

更新到最新版Google Chome后,可以明显发现,Accept-Encoding从原来的gzip, deflate, br变更为了gzip, deflate, br, zstd。表明Google Chrome正式开始支持zstd压缩。

长期以来,由于 zstd 缺少标准化的字典,Mozilla Firefox 等浏览器的开发者拒绝使用 zstd 作为 Content-Encoding 。

但目前 IETF HTTP 工作组正在起草一份 Compression Dictionary Transport 标准化文件,以允许网站提供适用于自身的外部字典。而这解决了 zstd 缺少标准化字典的问题。

既然当前Chrome已经支持zstd,那网络服务器方面(NGINX)也要跟上节奏,目前NGINX有一个开源的ZSTD模块:

可以让nginx可以像ngx_brotli模块一样支持zstd,不过该模块目前看有一些bug:

  1. 开启zstd压缩后内容替换功能失效(即便上游响应是非压缩)
    bugfix: fix module order to avoid taking effect before other modules such as sub filter module
  2. 在上游返回 content-length 异常时无限循环
    bugfix: fix zstd module infinite loop when upstream return content-length abnormal

两个bug都已经提交pull request了,目前尚未合并,我fork了一个版本,可以先用着:

以下为编译该模块的相关教程:

准备 Zstd 库

首先需要下载编译zstd,当然使用操作系统自带的库也是可以的,我是用容器构建的所以还是直接编译按照zstd了。

# 下载源码包
curl -fSL https://github.com/facebook/zstd/releases/download/v1.5.6/zstd-1.5.6.tar.gz -o zstd-1.5.6.tar.gz
# 解压缩
tar xzf zstd-1.5.6.tar.gz
# 编译安装
cd zstd-1.5.6
make && make install

集成 Zstd 到 Nginx

与 Brotli 类似,Zstd 压缩支持可以通过第三方模块集成到 Nginx。这里将使用我fork的模块。

# 克隆模块仓库
git clone --depth=10 https://github.com/HanadaLee/ngx_http_zstd_module.git ngx_http_zstd_module
# nginx编译参数,/path/to为克隆的模块仓库所在的路径,这里省略了其他编译参数,请自行添加
./configure --add-module=/path/to/ngx_http_zstd_module ...
# 编译nginx
make && make install

配置 Nginx 使用 Zstd

在 Nginx 的配置文件(nginx.conf)中,可以像配置 Gzip 压缩那样配置 Zstd 压缩。以下是我目前正在使用的配置:

zstd on;
zstd_min_length 1k;
zstd_comp_level 10;
zstd_types application/dash+xml application/eot application/font application/font-sfnt application/javascript application/json application/opentype application/otf application/pkcs7-mime application/protobuf application/rss+xml application/truetype application/ttf application/vnd.apple.mpegurl application/vnd.mapbox-vector-tile application/vnd.ms-fontobject application/xhtml+xml application/xml application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-httpd-cgi application/x-javascript application/x-mpegurl application/x-opentype application/x-otf application/x-perl application/x-ttf font/eot font/opentype font/otf font/ttf image/svg+xml text/css text/csv text/javascript text/js text/plain text/richtext text/tab-separated-values text/xml text/x-component text/x-java-source text/x-script;

brotli on;
brotli_min_length 1k;
brotli_comp_level 4;
brotli_types application/dash+xml application/eot application/font application/font-sfnt application/javascript application/json application/opentype application/otf application/pkcs7-mime application/protobuf application/rss+xml application/truetype application/ttf application/vnd.apple.mpegurl application/vnd.mapbox-vector-tile application/vnd.ms-fontobject application/xhtml+xml application/xml application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-httpd-cgi application/x-javascript application/x-mpegurl application/x-opentype application/x-otf application/x-perl application/x-ttf font/eot font/opentype font/otf font/ttf image/svg+xml text/css text/csv text/javascript text/js text/plain text/richtext text/tab-separated-values text/xml text/x-component text/x-java-source text/x-script;

gzip on;
gzip_min_length 1k;
gzip_comp_level 8;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
gzip_proxied any;
gzip_types application/dash+xml application/eot application/font application/font-sfnt application/javascript application/json application/opentype application/otf application/pkcs7-mime application/protobuf application/rss+xml application/truetype application/ttf application/vnd.apple.mpegurl application/vnd.mapbox-vector-tile application/vnd.ms-fontobject application/xhtml+xml application/xml application/x-font-opentype application/x-font-truetype application/x-font-ttf application/x-httpd-cgi application/x-javascript application/x-mpegurl application/x-opentype application/x-otf application/x-perl application/x-ttf font/eot font/opentype font/otf font/ttf image/svg+xml text/css text/csv text/javascript text/js text/plain text/richtext text/tab-separated-values text/xml text/x-component text/x-java-source text/x-script;

以上配置包含了三种压缩格式的处理逻辑,优先级是zstd > brotli > gzip。

效果

压缩率比较

* 注:仅供参考
原始文件:75.1 KB
zstd level 11:15.6 KB
brotli level 4:15.7 KB
gzip level 8:15.7 KB

讲道理在小文件下zstd的压缩效果跟brotli差不多或者直白来说更差,而且因为没有字典(RFC没有规定字典),使得zstd压缩率相比有字典时逊色不少。这里只是为了尝鲜,必要性其实不是很大,还是建议优先使用brotli。不过大文件下zstd的压缩效果还是要比brotli好很多的,无论是压缩率还是速度。

上一篇