Nginx 与 Brotli 混合压缩的实战配置:gzip 与 Brotli 的协商、CDN 回源与失效排查
在现代 Web 站点中,页面加载速度直接影响用户体验与搜索引擎排名。压缩传输是减少带宽消耗的关键手段,而 Nginx 对 gzip 与 Brotli 的支持已成为标配。然而,如何在 gzip 与 Brotli 之间正确协商,以及如何排查 CDN 回源与缓存失效,是许多站长实际遇到的难题。
Brotli 与 gzip 的协商机制
Nginx 在处理客户端请求时,会优先检查客户端是否支持 Brotli。现代浏览器(Chrome、Firefox、Edge)已内置 Brotli 支持,而旧版浏览器则回退到 gzip。正确的配置流程如下:
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
server {
listen 443 ssl http2;
server_name www.zz1984.com;
# 开启 Brotli 压缩,priority=highest 让 Brotli 优先
brotli on;
brotli_comp_level 6;
brotli_types * text/html text/css text/xml text/javascript application/javascript application/xml+rss application/atom+xml;
# 对不支持 Brotli 的客户端 fallback 到 gzip
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_min_length 1000;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml+rss application/atom+xml image/svg+xml;
}
CDN 回源与缓存失效的四大场景
1. Brotli 编码不匹配导致的 304 失效
当 CDN 缓存了经 Brotli 编码的资源,但回源时未携带 Accept-Encoding: br 头,服务端返回未经压缩的 gzip 版本。CDN 可能会基于 Content-Encoding 哲误判为“已缓存实体”,导致后续请求始终返回 304,用户始终拿到体积更大的 gzip 内容。
排查办法:确保 CDN 回源请求携带 Accept-Encoding: br, gzip,并检查 Origin 服务器返回的 Content-Encoding 与 Vary: Accept-Encoding 是否一致。
2. 静态资源提前编码与动态内容混淆
Brotli static 模块会提前压缩匹配的文件(如 .br 后缀),而动态生成的 HTML 需要运行时协商。如果静态 .br 文件被 CDN 缓存,而动态页面的 Vary 头设置不当,会导致缓存键不匹配,使用户拿到错误编码的资源。
3. TLS 与 ALPN 对 Brotli 的依赖
Brotli 的协商依赖 TLS 的 ALPN 扩展。如果 CDN 前置的 TLS 握手未正确传递 ALPN 信息,或 Origin 服务器的证书链配置不完整,客户端可能无法声明对 Brotli 的支持,从而被迫使用 gzip。
4. Cache-Control 与 max-age 的时间窗口
长期缓存的 Brotli 资源在内容更新时难以失效。若未在响应头中设置合理的 Cache-Control: max-age 或未使用索引文件版本控制,用户可能长时间看到过旧的压缩内容。
实战排查步骤
- 使用
curl -I -H "Accept-Encoding: br, gzip"查看服务器实际返回的Content-Encoding与Vary。 - 在 CDN 控制台确认回源请求头是否包含
Accept-Encoding。 - 检查 Nginx error.log 是否有
brotli decompress failed相关警告。 - 使用
chrome://net-internals/#http2查看浏览器实际选择的压缩算法。
结语
Brotli 相比 gzip 可节省 15%-25% 的带宽,但配置不当易引入缓存失效与编码不匹配的问题。掌握协商机制、回源头部与 CDN 缓存策略,方能在不牺牲兼容性的前提下获得最佳传输性能。