Brotli预压缩静态分发是降低CPU开销最有效方式:启用brotli_static on,构建时生成.br文件,Nginx直接sendfile发送,零运行时压缩;按资源类型分级设comp_level(HTML/JSON用2–4,JS/CSS用6,静态资源用8–11),并保留gzip_static作为兼容兜底。

直接启用 brotli on 动态压缩,在高并发下会让 CPU 快速拉满——这不是配置错了,而是设计使然。Brotli 的高压缩率是以计算为代价的,尤其在 level 9–11 时,单次压缩可能多耗 20–30ms,对 API 接口或 HTML 渲染路径尤为敏感。真正低开销、高收益的做法,是绕过运行时压缩,改用预压缩 + 静态分发。
用 brotli_static on 替代 brotli on
这是降低 CPU 消耗最有效的一招。它不压缩,只查文件:
-
原理:请求
/app.js时,Nginx 检查是否存在同名/app.js.br;有就直接 sendfile 发送,全程零 CPU 压缩开销 -
前提:前端构建阶段必须生成 .br 文件(如 Vite 用
vite-plugin-compression,Webpack 用compression-webpack-plugin) - 注意:.br 文件权限需为 Nginx worker 进程可读(常见坑:权限 600 或属主不对,导致静默跳过)
按资源类型分级设置 brotli_comp_level
统一设 11 是最大误区。不同资源对压缩率和响应延迟的敏感度差异很大:
-
HTML / JSON 接口响应:用
brotli_comp_level 2–4。实测压缩耗时降 60%,压缩率仍优于 Gzip 9 级 -
打包 JS/CSS(如 vendor-xxx.js):设
6。兼顾体积(~65% 压缩率)与首字节时间(TTFB) -
长期不变的静态资源(logo.svg、reset.css):可设
8–11,配合预压缩,CPU 无负担
保留 gzip 作为兜底,但禁用其动态压缩
双压缩不是为了叠加,而是兼容性保障。关键在于让 gzip 也走静态路径:
- 配置
gzip_static on,并确保所有 .js/.css 文件同时存在 .gz 和 .br 副本 - 关闭
gzip on(即不启用动态 Gzip),避免 Nginx 在 .br 或 .gz 缺失时 fallback 到 CPU 密集型实时压缩 - 必须开启
gzip_vary on和brotli_vary on,保证 CDN 和代理正确缓存不同编码版本
验证是否真省了 CPU
别只看配置,要确认实际行为:
- 检查响应头:
Content-Encoding: br且Vary: Accept-Encoding同时存在 - 用
nginx -V 2>&1 | grep brotli确认模块已编译进内核,否则brotli_static指令无效 - 压测对比:用 wrk 或 ab 对比开启前后 CPU 使用率(
top -p $(pgrep nginx)),重点关注 worker 进程的 %CPU


















