关于Brotli

Brotli最初发布于2015年,用于网络字体的离线压缩。Google软件工程师在2015年9月发布了包含通用无损数据压缩的Brotli增强版本,特别侧重于HTTP压缩。其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式API已被改进,增加更多压缩质量级别。新版本还展现了跨平台的性能改进,以及减少解码所需的内存。

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

使用brotli取代deflate来对文本文件压缩通常可以增加20%的压缩密度,而压缩与解压缩速度则大致不变。使用Brotli进行流压缩的内容编码类型已被提议使用“br”。

浏览器支持情况:

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

githab地址:https://github.com/google/ngx_brotli

brotli压缩率比gzip还要高,但是压缩时间比gzip略长 。所以这样的压缩算法,使用上比较偏向用在变动较少的项目。因为压缩一次建立cache后,整体就能优于gzip,但如果页面变动比较频繁,还是適合使用 gzip。
参考地址:https://cran.r-project.org/web/packages/brotli/vignettes/benchmarks.html

安装Brotli

环境说明:
nginx:1.16.1
nginx 安装目录:/usr/local/nginx

下载Brotli

cd /tmp
git clone https://github.com/google/ngx_brotli.git
cd /tmp/ngx_brotli/deps
rm -rf brotli
git clone https://github.com/google/brotli.git
cd /tmp/ngx_brotli
git submodule update --init

然后在下载google/brotli并解压到/usr/src/ngx_brotli/deps/brotli

方法一:重新编译

通过nginx -V查看原有的编译参数,在编译的时候通过--add-module=把模块编译进去。
比如:

./configure [nginx -V 原有的configure arguments] --add-module=/tmp/ngx_brotli
make && make install

方法二:编译动态模块

编译动态模块

cd /nginx-1.16.1
./configure --with-compat --add-dynamic-module=/tmp/ngx_brotli
make modules

等运行完成后,查看编译好的模块

ls objs/*.so

输出:

objs/ngx_http_brotli_filter_module.so  objs/ngx_http_brotli_static_module.so

将编译好的模块文件复制到nginx动态模块加载目录

cp objs/{ngx_http_brotli_filter_module.so,ngx_http_brotli_static_module.so} /usr/local/nginx/modules/

注册Brotli模块

为了方便管理nginx动态模块,建议新建一个modules.conf文件,单独管理动态模块。

touch /usr/local/nginx/conf/modules.conf

在/etc/nginx/nginx.conf配置文件里引入modules.conf文件,找到以下内容并修改:

pid        /var/run/nginx.pid;

include modules.conf;

打开/etc/nginx/modules.conf,注册刚才编译好的 Brotli 模块。

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

在我这个nginx-1.16.1版本中,通过nginx -t测试没通过,报nginx: [emerg] module "/usr/local/nginx/modules/ngx_http_brotli_filter_module.so" is not binary compatible in /usr/local/nginx/conf/modules.conf:1错误。
通过https://github.com/google/ngx_brotli/issues/106此issues中有说到不加--with-compat可以通过nginx测试。在我这版本中不加也不能通过测试。此问题待解决。

启用Brotli压缩

Brotli和gzip是可以并存的,无需关闭gzip。

/etc/nginx/nginx.conf开启Brotli:

http {
    ...
    # brotli
    brotli on;                                                                                           
    brotli_comp_level 6;                                                                                 
    brotli_buffers 16 8k;                                                                                
    brotli_min_length 20;                                                                                
    brotli_types text/plain text/css application/json                                                                                                                            
                 application/x-javascript text/xml application/xml                                                                          
                 application/xml+rss text/javascript application/javascript                                         
                 image/svg+xml;
    ...
}

gzip和br可以同时生效,意味着我们可以对基于 Node.js 等会在后台自动 Gzip 的站点,设置优先使用 brotli,所以在网站反代配置里加上如下配置,告知后端:前端不接受 Gzip 编码。

在反向代理配置文件代码中添加:

proxy_set_header Accept-Encoding "";

配置文件修改完后,通过nginx -t检查配置文件是否有错误。没错误则使用nginx -s reload重载生效。