Nginx 编译 ngx_brotli 为动态模块

Brotli 算法介绍

Brotli 基于 LZ77 算法的一个现代变体、霍夫曼编码和二阶上下文来建模。Google 软件工程师在 2015 年 9 月发布了包含通用无损数据压缩的 Brotli 增强版本,特别侧重于 HTTP 压缩。其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式API已被改进,增加更多压缩质量级别。

与常见的通用压缩算法不同,Brotli 使用一个预定义的 120 千字节字典。该字典包含超过 13000 个常用单词、短语和其他子字符串,这些来自一个文本和 HTML 文档的大型语料库。预定义的算法可以提升较小文件的压缩密度。

使用 Brotli 替换 Deflate 来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变。

Nginx 的官方预编译版本没有包含 Brotli 支持,需要手动编译添加。而较新版本的nginx (>1.9.11) 开始支持动态模块,只需编译好动态模块,在 nginx 运行时加载即可,不用重新编译 nginx。

Nginx 动态模块

Nginx dynamic module
Nginx dynamic module

浏览器支持情况

  • Mozilla Firefox 在 Firefox 44 中实现 Brotli。
  • Google Chrome 从 Chrome 49 开始支持 Brotli。
  • Opera 从 Opera 36 开始支持 Brotli。

系统环境

CentOS 7

Nginx 1.14.2/官方预编译稳定版

编译过程

源码下载

1
2
3
4
5
6
7
8
9
10
11
12
# 下载安装版本对应的nginx源码并解压,我的是1.14.2
wget http://nginx.org/download/nginx-1.14.2.tar.gz
x nginx-1.14.2.tar.gz

# 克隆ngx_brotli源码
cd nginx-1.14.2
git clone git@github.com:google/ngx_brotli.git

# 克隆ngx_brotli依赖库
cd ngx_brotli/
git submodule update --init
cd ../../nginx-1.14.2/

获得已安装版本的编译参数

1
nginx -V

如下:

1
2
3
4
5
nginx version: nginx/1.14.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

编译 ngx_brotli 为动态模块

编译参数添加 add-dynamic-module

1
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module--with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g-pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-dynamic-module=./ngx_brotli/

执行编译

1
make

最终得到两个 .so 文件:

1
2
nginx-1.14.2/objs/ngx_http_brotli_filter_module.so
nginx-1.14.2/objs/ngx_http_brotli_static_module.so

配置 nginx 使模块生效

将两个 .so 文件复制至 nginx modules 目录

1
sudo cp nginx-1.14.2/objs/*.so /etc/nginx/modules/

修改 nginx 压缩方式为 br

1
sudo vim /etc/nginx/nginx.conf

在配置文件开头添加下面两行,使nginx加载模块

1
2
load_module  modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

接下来在 http 段中添加

1
2
3
4
#Brotli Compression
brotli on;
brotli_comp_level 6;
brotli_types application/x-httpd-php application/javascript application/x-javascript application/xml application/json text/plain text/javascript text/css text/xml image/jpeg image/gif image/png image/svg+xml image/x-icon;

检查配置文件是否有错

1
sudo nginx -t

如果正常,即可重启 nginx 使改动生效

1
sudo systemctl restart nginx

使用浏览器开发者工具,在 Network 中查看资源响应头是否已经变为 Content-Encoding:br

打完收工!


Writing Enriches Life.