如何动态更新 Nginx 模块,使用新一代压缩算法 Brotli
测试环境
内容协商
在介绍 Brotli 之前,先说一下 HTTP 内容协商
有时候,同一个 URL 可以提供多份不同的文档,这就要求服务端和客户端之间有一个选择最合适版本的机制,这就是内容协商
HTTP 的内容协商的其中一种方式:服务端根据客户端发送的请求头中某些字段自动发送最合适的版本。可以用于这个机制的请求头字段又分两种:内容协商专用字段(Accept 字段)、其他字段
字段情况,详见下表:
请求头字段
说明
响应头字段
Accept
告知服务器发送何种媒体类型
Content-Type
Accept-Language
告知服务器发送何种语言
Content-Language
Accept-Charset
告知服务器发送何种字符集
Content-Type
Accept-Encoding
告知服务器采用何种压缩方式
Content-Encoding
例如客户端发送以下请求头:
1
Accept-Encoding:gzip,deflate,br
表示支持采用 gzip、deflate 或 br 压缩过的资源
浏览器的响应头可能是这样的:
详情可参考:Here
什么是 Brotli
从上面的内容了解到,我们控制使用压缩的资源,除了有 Gzip 外,还有 br,而这个 br 就是我这里要说的 Brotli
Brotli is a generic-purpose lossless compression algorithm that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling, with a compression ratio comparable to the best currently available general-purpose compression methods. It is similar in speed with deflate but offers more dense compression.
Brotli 是基于 LZ77 算法的一个现代变体、霍夫曼编码和二阶上下文建模。Google 软件工程师在 2015 年 9 月发布了包含通用无损数据压缩的 Brotli 增强版本,特别侧重于 HTTP 压缩。其中的编码器被部分改写以提高压缩比,编码器和解码器都提高了速度,流式 API 已被改进,增加更多压缩质量级别。
与常见的通用压缩算法不同,Brotli 使用一个预定义的 120 千字节字典。该字典包含超过 13000 个常用单词、短语和其他子字符串,这些来自一个文本和 HTML 文档的大型语料库。预定义的算法可以提升较小文件的压缩密度。
使用 Brotli 替换 Deflate 来对文本文件压缩通常可以增加 20%的压缩密度,而压缩与解压缩速度则大致不变。
浏览器支持情况
Mozilla Firefox 在 Firefox 44 中实现 Brotli。
Google Chrome 从 Chrome 49 开始支持 Brotli。
Opera 从 Opera 36 开始支持 Brotli。
安装与配置过程
安装需要用到开发工具
1
yum -y groupinstall 'Development Tools'
因为我们是编译安装 nginx 来定制自己的模块,所以需要安装缺少的依赖包
1
yum -y install gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel
安装 libbrotli
1
2
3
4
5
6
cd /usr/local/src/
git clone https://github.com/bagder/libbrotli
cd libbrotli
./autogen.sh
./configure
make && make install
安装 ngx_brotli
1
2
3
cd / usr / local / src /
git clone https ://github.com/google/ngx_brotli
cd ngx_brotli && git submodule update -- init
安装 Nginx
安装初始化依赖
1
sudo yum install yum-utils
创建/etc/yum.repos.d/nginx.repo
文件并根据自己的系统填写适当的 Linux 版本和发行版型号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
安装 Nginx
下载 Nginx
这里使用 nginx-1.14.2
1
2
3
cd /usr/local/src/
wget http://nginx.org/download/nginx-1.14.2.tar.gz
tar -xvzf nginx-1.14.2.tar.gz && rm -rf nginx-1.14.2.tar.gz
获取 Nginx Arguments
1
2
3
nginx -V
# 格式化输出
nginx -V 2>&1 | sed "s/\s\+--/\n --/g"
整理新的 Arguments
根据获取到的 configure arguments 和上面软件的位置,重新整理 configure arguments
然后再加上 --add-module=/usr/local/src/ngx_brotli
,一下为我的安装实例,大家可以根据自己的情况动态修改
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
./ 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 \
-- add - module =/ usr / local / src / ngx_brotli
开始安装和编译
1
2
3
cd /usr/local/src/nginx-1.14.2
./configure [这里是你的原Arguments] --add-module=/usr/local/src/ngx_brotli
make && make install
检查是否安装正常
找到 Nginx 的全局配置文件
如果检测安装正常的话,可以开始配置,该配置文件一般为 nginx.conf
在合适的位置插入下面代码
1
2
3
4
[[Brotli]] Compression
brotli on;
brotli_comp_level 6;
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;
再次检测是否正常
重启 Nginx
如果正常的话,恭喜你,你已经配置完成了,重启一下 Nginx 即可
1
systemctl restart nginx
检查是否生效
打开你的网页,用 chrome 开发者工具调试,在 Network 那,发现有content-encoding:br
可能的报错
如果在测试或者重载时, Nginx 报错如下:
1
nginx: error while loading shared libraries: libbrotlienc.so.1: cannot open shared object file: No such file or directory
解决方法是把对应的库文件在 /lib(64) 或者 /usr/lib(64) 中做上软链接:
1
2
3
4
5
# 64 位系统
$ ln -s /usr/local/lib/libbrotlienc.so.1 /lib64
# 32 位系统
$ ln -s /usr/local/lib/libbrotlienc.so.1 /lib
参考