### 什么是Brotli ? Brotli是Google在2015年推出的压缩算法,目前各大浏览器均已支持Brotli,相比Gzip,有着更高的压缩率(尤其在处理CSS、JS、HTML这类文件),解压速度却相差无几,这意味着它有着**更小的数据传输量**,对于网络环境较差、带宽受限的用户或移动端访问者而言,能直接转化为**更快的页面加载速度**和**更流畅的交互体验**。 所以对于弱网环境下(如跨国传输),一个可行的优化思路是优先使用Brotli,对于不支持Brotli的浏览器,再回退到Gzip。 当然,更高的压缩率比如会带来压缩时更大的CPU开销,所以我们接下来也会介绍预压缩这种解决方案来缓解这个问题。 ### 启用Brotli #### 编译具有brotli模块的Nginx ##### 获取源代码 先克隆**[ngx\_brotli](https://github.com/google/ngx_brotli)**源代码到本地 ```shell git clone ``` 始化和同步ngx\_brotli的子模块 ```shell cd ngx_brotli && git submodule update --init ``` 下载Nginx的源码并解压 ``` wget https://nginx.org/download/nginx-1.28.0.tar.gz && tar zxvf nginx-1.28.0.tar.gz ``` ##### 保留原编译参数并编译 安装依赖库 ``` apt update && apt install libbrotli-dev ``` 进入源代码目录 ``` cd nginx-1.28.0 ``` 首先查看当前的Nginx编译参数 ``` nginx -V ``` 生成Makefile并编译 ```shell ./configure [原参数] --add-module=[ngx_brotli路径] make ``` 编译好的二进制在 `objs/nginx` ,先把原来的nginx二进制复制一份用于防止意外,然后替换原来的二进制文件 #### 编辑nginx配置文件 在http块下加入 ``` http { ... brotli on; brotli_comp_level 6; brotli_min_length 512; brotli_types text/plain text/javascript text/css text/xml text/x-component font/opentype application/json; brotli_static on; ... ``` 参数解释 | 指令名称 | 语法格式 | 默认值 | 作用域 | 描述 | 重要参数说明 | | --------------------- | ------------------------ | ----------- | -------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------- | | **brotli_static** | `on` , `off` , `always` | `off` | http, server, location | 启用/禁用预压缩文件(.br)检测 | -`on`:客户端支持Brotli时返回.br文件- `always`:强制返回.br文件(无论客户端是否支持) | | **brotli** | `on` , `off` | `off` | http, server, location, if | 启用/禁用动态响应压缩 | 需与`brotli_types`配合使用 | | **brotli_types** | ` [mime_type ...]` , `*` | `text/html` | http, server, location | 指定启用压缩的MIME类型 | -`*`:压缩所有类型- `text/html` 始终被压缩(无需声明) | | **brotli_buffers** | ` ` | - | http, server, location | **已废弃**(配置会被忽略) | 历史遗留参数,无实际作用 | | **brotli_comp_level** | `` | `6` | http, server, location | 设置动态压缩级别 | **范围:0-11**- 0:最快(最低压缩)- 11:最慢(最高压缩) | | **brotli_window** | `` | `512k` | http, server, location | 设置滑动窗口大小(影响压缩率和内存) | **有效值**:1k,2k,4k,8k,16k,32k,64k,128k,256k,512k,1m,2m,4m,8m,16m | | **brotli_min_length** | `` | `20` | http, server, location | 设置启用压缩的最小响应长度(仅依据Content-Length头) | 单位:字节**建议值**:≥256(避免小文件压缩得不偿失) | ### 处理Brotli预压缩 预压缩可以减少CPU开销,由于动态压缩会在每次请求(尤其是高并发下)对CPU造成压力,无论你是想优化并发性能还是想得到更高的压缩率,都建议使用Brotli预压缩,在打开了 `brotli_static` 项的时候nginx会先检测当前访问的文件是否有 `.br` 的预压缩文件并返回 (如果有的话,直接返回预压缩文件,没有的话再根据 `brotli` 项是否开启,决定是否进行动态压缩)。 所以我们可以写一个脚本去处理预压缩 ```shell #!/bin/bash WEB_ROOT="/aaa/www" 网页根目录 COMP_LEVEL=11 # 压缩级别 (0-11) LOG_FILE="/var/log/br.log" #存储日志的路径 # 创建日志目录 mkdir -p "$(dirname "$LOG_FILE")" # 查找需要压缩的文件 find "$WEB_ROOT" -type f \( \ -name "*.html" -o \ -name "*.css" -o \ -name "*.js" -o \ -name "*.xml" -o \ -name "*.json" -o \ -name "*.svg" -o \ -name "*.ttf" -o \ -name "*.woff" -o \ -name "*.woff2" \ \) | while read -r file; do # 跳过已压缩文件(如果源文件未修改) if [ -f "$file.br" ] && [ "$file" -ot "$file.br" ]; then continue fi # 记录压缩开始时间 start_time=$(date +%s) # 执行压缩(修正后的命令) brotli --quality="$COMP_LEVEL" --force --keep --output="$file.br" "$file" # 记录压缩结果 end_time=$(date +%s) orig_size=$(stat -c%s "$file") comp_size=$(stat -c%s "$file.br") ratio=$(echo "scale=2; $comp_size * 100 / $orig_size" | bc) echo "[$(date '+%Y-%m-%d %H:%M:%S')] Compressed: $file" >> "$LOG_FILE" echo " Original: $orig_size bytes, Compressed: $comp_size bytes, Ratio: ${ratio}%" >> "$LOG_FILE" echo " Time taken: $((end_time - start_time)) seconds" >> "$LOG_FILE" echo "----------------------------------------" >> "$LOG_FILE" done echo "Completed. Log saved to: $LOG_FILE" ``` 这样,在每次文件发生变化的时候都运行一次,我们就可以使用最高的压缩率和最小的CPU开销来响应请求了。 Loading... ### 什么是Brotli ? Brotli是Google在2015年推出的压缩算法,目前各大浏览器均已支持Brotli,相比Gzip,有着更高的压缩率(尤其在处理CSS、JS、HTML这类文件),解压速度却相差无几,这意味着它有着**更小的数据传输量**,对于网络环境较差、带宽受限的用户或移动端访问者而言,能直接转化为**更快的页面加载速度**和**更流畅的交互体验**。 所以对于弱网环境下(如跨国传输),一个可行的优化思路是优先使用Brotli,对于不支持Brotli的浏览器,再回退到Gzip。 当然,更高的压缩率比如会带来压缩时更大的CPU开销,所以我们接下来也会介绍预压缩这种解决方案来缓解这个问题。 ### 启用Brotli #### 编译具有brotli模块的Nginx ##### 获取源代码 先克隆**[ngx\_brotli](https://github.com/google/ngx_brotli)**源代码到本地 ```shell git clone ``` 始化和同步ngx\_brotli的子模块 ```shell cd ngx_brotli && git submodule update --init ``` 下载Nginx的源码并解压 ``` wget https://nginx.org/download/nginx-1.28.0.tar.gz && tar zxvf nginx-1.28.0.tar.gz ``` ##### 保留原编译参数并编译 安装依赖库 ``` apt update && apt install libbrotli-dev ``` 进入源代码目录 ``` cd nginx-1.28.0 ``` 首先查看当前的Nginx编译参数 ``` nginx -V ``` 生成Makefile并编译 ```shell ./configure [原参数] --add-module=[ngx_brotli路径] make ``` 编译好的二进制在 `objs/nginx` ,先把原来的nginx二进制复制一份用于防止意外,然后替换原来的二进制文件 #### 编辑nginx配置文件 在http块下加入 ``` http { ... brotli on; brotli_comp_level 6; brotli_min_length 512; brotli_types text/plain text/javascript text/css text/xml text/x-component font/opentype application/json; brotli_static on; ... ``` 参数解释 | 指令名称 | 语法格式 | 默认值 | 作用域 | 描述 | 重要参数说明 | | --------------------- | ------------------------ | ----------- | -------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------- | | **brotli_static** | `on` , `off` , `always` | `off` | http, server, location | 启用/禁用预压缩文件(.br)检测 | -`on`:客户端支持Brotli时返回.br文件<br />- `always`:强制返回.br文件(无论客户端是否支持) | | **brotli** | `on` , `off` | `off` | http, server, location, if | 启用/禁用动态响应压缩 | 需与`brotli_types`配合使用 | | **brotli_types** | ` [mime_type ...]` , `*` | `text/html` | http, server, location | 指定启用压缩的MIME类型 | -`*`:压缩所有类型<br />- `text/html` 始终被压缩(无需声明) | | **brotli_buffers** | ` ` | - | http, server, location | **已废弃**(配置会被忽略) | 历史遗留参数,无实际作用 | | **brotli_comp_level** | `` | `6` | http, server, location | 设置动态压缩级别 | **范围:0-11**- 0:最快(最低压缩)- 11:最慢(最高压缩) | | **brotli_window** | `` | `512k` | http, server, location | 设置滑动窗口大小(影响压缩率和内存) | **有效值**:1k,2k,4k,8k,16k,32k,64k,128k,256k,512k,1m,2m,4m,8m,16m | | **brotli_min_length** | `` | `20` | http, server, location | 设置启用压缩的最小响应长度(仅依据Content-Length头) | 单位:字节**建议值**:≥256(避免小文件压缩得不偿失) | ### 处理Brotli预压缩 预压缩可以减少CPU开销,由于动态压缩会在每次请求(尤其是高并发下)对CPU造成压力,无论你是想优化并发性能还是想得到更高的压缩率,都建议使用Brotli预压缩,在打开了 `brotli_static` 项的时候nginx会先检测当前访问的文件是否有 `.br` 的预压缩文件并返回 (如果有的话,直接返回预压缩文件,没有的话再根据 `brotli` 项是否开启,决定是否进行动态压缩)。 所以我们可以写一个脚本去处理预压缩 ```shell #!/bin/bash WEB_ROOT="/aaa/www" 网页根目录 COMP_LEVEL=11 # 压缩级别 (0-11) LOG_FILE="/var/log/br.log" #存储日志的路径 # 创建日志目录 mkdir -p "$(dirname "$LOG_FILE")" # 查找需要压缩的文件 find "$WEB_ROOT" -type f \( \ -name "*.html" -o \ -name "*.css" -o \ -name "*.js" -o \ -name "*.xml" -o \ -name "*.json" -o \ -name "*.svg" -o \ -name "*.ttf" -o \ -name "*.woff" -o \ -name "*.woff2" \ \) | while read -r file; do # 跳过已压缩文件(如果源文件未修改) if [ -f "$file.br" ] && [ "$file" -ot "$file.br" ]; then continue fi # 记录压缩开始时间 start_time=$(date +%s) # 执行压缩(修正后的命令) brotli --quality="$COMP_LEVEL" --force --keep --output="$file.br" "$file" # 记录压缩结果 end_time=$(date +%s) orig_size=$(stat -c%s "$file") comp_size=$(stat -c%s "$file.br") ratio=$(echo "scale=2; $comp_size * 100 / $orig_size" | bc) echo "[$(date '+%Y-%m-%d %H:%M:%S')] Compressed: $file" >> "$LOG_FILE" echo " Original: $orig_size bytes, Compressed: $comp_size bytes, Ratio: ${ratio}%" >> "$LOG_FILE" echo " Time taken: $((end_time - start_time)) seconds" >> "$LOG_FILE" echo "----------------------------------------" >> "$LOG_FILE" done echo "Completed. Log saved to: $LOG_FILE" ``` 这样,在每次文件发生变化的时候都运行一次,我们就可以使用最高的压缩率和最小的CPU开销来响应请求了。 最后修改:2025 年 08 月 25 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏