为Nginx添加Brotli压缩算法支持

  Brotli是Google推出的一个新型压缩算法,与传统的gzip相比可以大幅提高压缩率,目前各大浏览器Chrome/Firefox/Opera均已支持Brotli算法。但是目前Nginx官方并没有默认集成Brotli算法,还需要手工编译以开启Nginx对Brotli算法的支持。呉真经过寻找后,发现Nginx Plus以及GetPageSpeed Service提供了预编译好的Brotli动态模块,但是这两者都是需要收费的商业服务。

编译Brotli动态模块

  由于呉真有多台使用Nginx的Web服务器,且每台Web服务器均使用Nginx官方源安装的最新版本Nginx,因此呉真决定使用Nginx动态模块的方式编译Brotli模块,这使得每次Nginx更新后,仅需要在一台服务器上编译出新的动态模块,即可无缝移植到其他的服务器中。如果你使用的是其他方式安装的Nginx,其基本原理都是相同的,可以自行修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 在这里先定义你使用的Nginx版本
NGINX_VERSION="nginx-1.17.4"

# 安装编译的一些依赖
yum -y install openssl-devel git make gcc gcc-c++

# 克隆ngx_brotli及brotli项目
cd /usr/local/src
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli/
git submodule update --init

# 下载Nginx源码
cd ../
wget https://nginx.org/download/$NGINX_VERSION.tar.gz -O $NGINX_VERSION.tar.gz
tar -xzvf $NGINX_VERSION.tar.gz
cd $NGINX_VERSION

  这里需要注意的是,编译Nginx时,必须保持与现有的Nginx相同的编译参数。使用nginx -V命令查看当前编译参数,并复制configure arguments后的参数。

1
2
3
4
5
6
nginx -V
> nginx version: nginx/1.17.4
> built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (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'

  使用旧的编译参数配置新的Nginx编译参数。

1
2
./configure 你复制的当前编译参数 --add-dynamic-module=../ngx_brotli/
make

  如果编译成功,你可以看到生成了两个.so文件ngx_http_brotli_filter_module.songx_http_brotli_static_module.so

1
2
3
4
cd objs/
ll | grep .so
> -rwxr-xr-x 1 root root 5.1M 10月 12 09:10 ngx_http_brotli_filter_module.so
> -rwxr-xr-x 1 root root 115K 10月 12 09:10 ngx_http_brotli_static_module.so

  将两个编译好的动态库复制到nginx的modules目录下。

1
cp *.so /etc/nginx/modules

配置Nginx开启Brotli支持

  在Nginx全局配置下载入Brotli动态模块。

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

  在需要开启Brotli支持的虚拟主机下,启用Brotli压缩。

1
2
3
4
# brotli
brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

  重启Nginx,你可以发现,对于静态文件的响应头,已经开启了Brotli支持。

1
2
3
4
> content-encoding: br
> content-type: text/html; charset=utf-8
> server: nginx
> status: 200

呉真预编译的Brotli动态模块

方法一:直接下载预编译的Brotli动态模块

  在这里,呉真提供一个预先编译好的Brotli动态模块,如果你使用的是CentOS 7系统,且使用Nginx官方源安装的Nginx,可以直接下载使用,呉真会保持与Nginx官方仓库的同步,CentOS 8系统目前正在适配中。

1
2
3
4
cd /etc/nginx/modules
wget https://raw.githubusercontent.com/kuretru/Scripts-Collection/master/files/nginx/ngx_http_brotli_filter_module.so.el7 -O ngx_http_brotli_filter_module.so
wget https://raw.githubusercontent.com/kuretru/Scripts-Collection/master/files/nginx/ngx_http_brotli_static_module.so.el7 -O ngx_http_brotli_static_module.so
chmod 755 *.so
方法二:使用呉真RPM仓库安装

  为了方便使用,呉真搭建了一个基于Github Page的RPM仓库,用于提供编译好的Brotli动态模块,可以使用Yum一键安装。

1
2
wget http://kuretru.github.io/packages/kuretru.repo -O /etc/yum.repos.d/kuretru.repo
yum -y install nginx-module-brotli