nginx添加Brotli模块

Brotli是谷歌在2015 年 9 月推出的无损压缩算法,通过变种的 LZ77 算法、Huffman 编码以及二阶文本建模等方式进行数据压缩,能达到比Gzip更高的压缩率。

将此算法使用于网站静态文件传输时的压缩处理,能有效减少网站传输的内容大小,加速网站加载速度,提升网站终端用户的使用体验。

谷歌官方提供了此算法的nginx module:ngx_brotli版本,本文内容即介绍如何在已安装的nginx上新增ngx_brotli模块开启Brotli压缩,本文内容同样适用于在已安装的nginx上增加其他nginx模块。

查看当前nginx安装信息

输入:

nginx -V

输出示例:

nginx version: nginx/1.16.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
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 --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

configure arguments后的信息为当前安装的nginx的配置信息,基于此配置,在加上新的模块配置进行编译,即可得到增加了新模块的nginx可执行程序文件。

其中,需要注意的参数:

  • nginx version:当前nginx版本,当前为1.16.1
  • --sbin-path:当前nginx编译完的可执行文件路径,当前为/usr/sbin/nginx

下载新模块

从插件提供方提供的下载地址下载模块源代码。

下载源码包

进入官网下载与当前nginx版本相同的源码包,以当前1.16.1为例:

wget http://nginx.org/download/nginx-1.16.1.tar.gz

解压源码包:

tar -zxvf nginx-1.16.1.tar.gz

编译设置

进入解压出来的nginx源码包目录:

cd nginx-1.16.1

添加配置:

./configure --add-module=新模块路径 源配置信息
  • 新模块路径即是之前下载的新模块源码包路径
  • 源配置信息则是nginx -V时configure arguments后的全部配置信息

以我当前操作为例,完整命令为:

./configure --add-module=/usr/lib64/nginx/modules/ngx_brotli --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 --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

第一次执行出错,出错信息:

./configure: error: Brotli library is missing from the /usr directory.

Please make sure that the git submodule has been checked out:

    cd /usr/lib64/nginx/modules/ngx_brotli && git submodule update --init && cd /release/nginx-1.16.1

原因是新增的ngx_brotli模块缺少相应的依赖库,若安装的不是ngx_brotli模块不一定会出现此错误,执行错误信息最后一行提示的命令即可解决:

cd /usr/lib64/nginx/modules/ngx_brotli && git submodule update --init && cd /release/nginx-1.16.1

或进入ngx_brotli源码包所在的文件夹目录下的deps/brotli,将brotli载下来也可解决此问题:

git clone https://github.com/google/brotli.git

除了上面的错误是新增的ngx_brotli模块引发的错误,添加编译配置的时候还经常会因为缺少某些依赖库而报错,根据错误提示安装相应的依赖后重新执行设置编译配置的命令即可。

列举几个常出现的依赖库缺失错误:

错误信息:

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option.

安装依赖:

yum -y install pcre-devel

错误信息:

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.

安装依赖:

yum -y install openssl-devel

错误信息:

./configure: error: the HTTP XSLT module requires the libxml2/libxslt
libraries. You can either do not enable the module or install the libraries.

安装依赖:

yum -y install libxslt-devel

错误信息:

./configure: error: the HTTP image filter module requires the GD library.
You can either do not enable the module or install the libraries.

安装依赖:

yum -y install gd-devel

错误信息:

./configure: error: perl module ExtUtils::Embed is required

安装依赖:

yum -y install perl-ExtUtils-Embed

错误信息:

./configure: error: the Google perftools module requires the Google perftools
library. You can either do not enable the module or install the library.

安装依赖:

yum -y install gperftools-devel

重新执行配置的命令,最终成功可以看到输出信息末尾会提示:

Configuration summary
  + using threads
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/etc/nginx"
  nginx binary file: "/usr/sbin/nginx"
  nginx modules path: "/usr/lib64/nginx/modules"
  nginx configuration prefix: "/etc/nginx"
  nginx configuration file: "/etc/nginx/nginx.conf"
  nginx pid file: "/var/run/nginx.pid"
  nginx error log file: "/var/log/nginx/error.log"
  nginx http access log file: "/var/log/nginx/access.log"
  nginx http client request body temporary files: "/var/cache/nginx/client_temp"
  nginx http proxy temporary files: "/var/cache/nginx/proxy_temp"
  nginx http fastcgi temporary files: "/var/cache/nginx/fastcgi_temp"
  nginx http uwsgi temporary files: "/var/cache/nginx/uwsgi_temp"
  nginx http scgi temporary files: "/var/cache/nginx/scgi_temp"

编译

nginx源代码目录下执行编译命令:

make

通常新安装nginx的时候这边会在编译时一起执行安装的命令:make install,但由于我们已经安装过nginx了,此时执行install会覆盖原来的可执行文件,所以先make,之后手动备份原来的版本之后在覆盖。

编译完成后进入当前目录下的objs目录就能看到编译完的nginx可执行文件,文件名就叫nginx,不带任何文件后缀。

备份旧版本

进入查看当前nginx配置中看到的--sbin-path的路径,备份当前版本nginx:

cd /usr/sbin/
cp nginx nginx_backup

覆盖旧版本

进入nginx源码包目录/objs目录下,将刚才编译完的新的可执行文件复制到配置中的sbin-path也就是/usr/sbin/nginx目录中即可:

cp nginx /usr/sbin/nginx

若提示:

cp: 无法创建普通文件"/usr/sbin/nginx": 文本文件忙

则需先停止nginx服务的运行:

service nginx stop

检查新配置是否生效

重新启动nginx:

service nginx start

查看nginx配置信息:

nginx -V

输出:

nginx version: nginx/1.16.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --add-module=/usr/lib64/nginx/modules/ngx_brotli --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 --param=ssp-buffer-size=4 -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

可以看到configure arguments参数后有一项--add-module=/usr/lib64/nginx/modules/ngx_brotli,证明新增了模块的nginx替换成功了,此时删除nginx的源码包和ngx_brotli的源码包不影响已经编译完的nginx。

brotli配置

ngx_brotli的配置层级位于nginx配置的HTTP块中。

可选配置项:

  • brotli:on|off,启用、禁用brotli
  • brotli_static:on|off|always,默认值off,启用或禁用对带有.br 扩展名的预压缩文件的检查。使用该always值,在所有情况下都使用预压缩文件,而无需检查客户端是否支持它。
  • brotli_types:<mime_type> [..],指定允许进行压缩的文件类型,*表示所有类型。
  • brotli_buffers ,默认值32 4k|16 8k,请求缓冲区的数量和大小,已被弃用可忽略。
  • brotli_comp_level,默认值6,压缩等级,可选值0到11,等级越高压缩比越大,但更吃CPU资源,压缩的时间也更久,根据需要调整,一般6-9即可。
  • brotli_window:1k|2k|4k|8k|16k|32k|64k|128k|256k|512k|1m|2m|4m|8m|16m,默认值512k,窗口值。
  • brotli_min_length,默认值20,指定压缩数据的最小长度,只有大于或等于最小长度才会对其压缩,该值由Content-Length确定。

brotli和gzip可以共存,在支持brotli的浏览器上将会优先使用brotli,配置示例:

http {
    ......省略其他配置......
    
    # 开启gzip压缩
    gzip  on;
    gzip_buffers 32 4K;
    gzip_comp_level 6;
    gzip_min_length 200;
    gzip_types text/plain text/css text/xml application/xml application/json text/javascript application/javascript application/x-javascript;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;

    # 开启brotli压缩协议的支持
    brotli on;
    brotli_types text/plain text/css text/xml application/xml application/json text/javascript application/javascript application/x-javascript;
    brotli_static off;
    brotli_comp_level 8;
    brotli_window 512k;
    brotli_min_length 20;

    ......省略其他配置......
}