Nginx 开启 Brotli 教程
Brotli 是 google 开发的文本压缩算法,比起gzip可能会有高达37%的提升。主流浏览器都支持br算法,强烈大家升级改算法。使用算法的前提是启用了 https,因为 http 请求中 request header 里的 Accept-Encoding: gzip, deflate 是没有 br 的。
一、内容协商
在介绍 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 压缩过的资源
浏览器的响应头可能是这样的:
1 |
Content-Encoding: gzip |
如果你的服务器支持br压缩会反回:
二、什么是 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。
Brotli压缩算法应用在HTTP请求流程,如下:
- 用户访问支持Brotli压缩的HTTP服务器上的网站或者Web应用
- 浏览器通过使用Accept-Encoding标头通知HTTP服务器它支持解压缩的内容类型
- HTTP服务器根据请求中包含的压缩算法决定要哪种压缩内容
- 服务器通过返回头部Content-Encoding向浏览器端表明数据的压缩方式
- 浏览器将数据解压并展示在页面上
三、安装与配置
本教程是在原来已安装nginx,但没有编译br模块的前提下,增加br模块,开始前需要先关闭nginx服务。
安装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 2 3 4 |
cd /usr/local/src wget http://nginx.org/download/nginx-1.18.0.tar.gz tar -zxvf nginx-1.18.0.tar.gz cd nginx-1.18.0 |
本站nginx使用 nginx-1.18.0
获取编译参数Nginx Arguments
1 |
nginx -V |
得到
1 2 3 4 5 6 |
[root@VM_0_16_centos ~]# nginx -V nginx version: nginx/1.18.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) built with OpenSSL 1.1.1d 10 Sep 2019 TLS SNI support enabled configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-openssl=/usr/local/src/openssl-1.1.1d --with-openssl-opt='enable-weak-ssl-ciphers' --with-ld-opt='-ljemalloc' |
整理新的Arguments
根据获取到的configure arguments和上面软件的位置,重新整理configure arguments
然后再加上 --add-module=/usr/local/src/ngx_brotli
开始安装和编译
1 2 3 |
cd /usr/local/src/nginx-1.18.0 ./configure [nginx -v输出的 configure arguments ] --add-module=/usr/local/src/ngx_brotli make && make install |
完整的例子是
1 2 3 |
cd /usr/local/src/nginx-1.18.0 ./configure --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_sub_module --with-stream --with-stream_ssl_module --with-openssl=/usr/local/src/openssl-1.1.1d --with-openssl-opt='enable-weak-ssl-ciphers' --with-ld-opt='-ljemalloc' --add-module=/usr/local/src/ngx_brotli make -j4 && make install |
configure检查
1 2 |
adding module in /usr/local/src/ngx_brotli + ngx_brotli was configured |
检查是否安装正常
1 2 |
nginx -V nginx -t |
找到Nginx的全局配置文件
/usr/local/nginx/conf/nginx.conf
在合适的位置插入下面代码
1 2 3 4 |
#Brotli Compression brotli on; # for static compression, explained later brotli_comp_level 6; # this setting can vary from 1-11 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; |
例如:Brotli和gzip是可以并存的,无需关闭gzip。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
http { ... # gzip gzip on; gzip_min_length 1k; gzip_buffers 4 32k; gzip_http_version 1.1; gzip_comp_level 5; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; gzip_vary on; gzip_proxied any; gzip_disable "MSIE [1-6]\."; # 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; ... } |
检测配置是否正常
1 |
nginx -t |
重启Nginx
如果配置不报错,重启nginx,使其配置生效。
四、检查br是否生效
curl检测gzip编码
1 2 3 4 5 6 7 8 9 10 |
[root@VM_0_16_centos nginx-1.18.0]# curl -IL https://blog.redis.com.cn -H "Accept-Encoding: gzip" HTTP/1.1 200 OK Server: nginx Date: Sat, 09 May 2020 09:47:22 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding X-Powered-By: PHP/7.3.11 Link: <https://blog.redis.com.cn/wp-json/>; rel="https://api.w.org/" Content-Encoding: gzip |
curl检测br编码
未增加配置前:
1 2 3 4 5 6 7 8 9 |
[root@VM_0_16_centos sbin]# curl -IL https://blog.redis.com.cn -H "Accept-Encoding: br" HTTP/1.1 200 OK Server: nginx Date: Sat, 09 May 2020 09:59:54 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding X-Powered-By: PHP/7.3.11 Link: <https://blog.redis.com.cn/wp-json/>; rel="https://api.w.org/" |
增加br配置后:
1 2 3 4 5 6 7 8 9 10 |
[root@VM_0_16_centos conf]# curl -IL https://blog.redis.com.cn -H "Accept-Encoding: br" HTTP/1.1 200 OK Server: nginx Date: Sat, 09 May 2020 10:02:39 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive Vary: Accept-Encoding X-Powered-By: PHP/7.3.11 Link: <https://blog.redis.com.cn/wp-json/>; rel="https://api.w.org/" Content-Encoding: br |
或者使用浏览器工具:
检查 > Network > Headers > "Response Headers" > "Content-Encoding" header,发现有content-encoding:br
高级应用:
gzip和br可以同时生效,意味着我们可以对基于 Node.js 等会在后台自动 Gzip 的站点,设置优先使用 brotli,所以在网站反代配置里加上如下配置,告知后端:前端不接受 Gzip 编码。
在反向代理配置文件代码中添加:
1 |
proxy_set_header Accept-Encoding ""; |
例如:
1 2 3 4 5 6 7 8 9 |
erver { ... location / { ... proxy_set_header Accept-Encoding ""; ... } ... } |
参考:
https://www.linpx.com/p/replace-the-gzip-nginx-configuration-tutorial-brotli.html