Nginx 1.24 上同时装了 brotli 模块并保留 gzip on,日志里蜘蛛请求的响应码是 200,但内容长度只有正常的三分之一,快照里正文是乱码,浏览器访问却一切正常。
一开始怀疑是「压缩级别设成 11,大页面压缩超时后输出被截断」,查了一圈,方向不对。
真正麻烦的地方在于,几个原因的现象几乎一样。brotli 在 gzip 之前生效,Content-Encoding 被写了两遍。少数情况下是上游 CDN 又把 br 转成 gzip,字符集和编码对不上。
不容易想到的是,Vary 头里只写了 Accept-Encoding 之外的值,缓存串了版本。
先看响应头里的编码声明
curl -sI -H 'Accept-Encoding: br,gzip' https://www.example.com/ | grep -i -E 'content-encoding|vary|content-length'
接着分别只用一种编码取正文长度
curl -s -H 'Accept-Encoding: gzip' https://www.example.com/ | wc -c
再往下在 Nginx 里只保留一种压缩
brotli on;
gzip off;
剩下的就是确认压缩级别不会拖到超时
brotli_comp_level 5;
恢复的判定其实很直接。响应头里只剩一个 Content-Encoding,正文长度恢复到正常值,快照和浏览器渲染一致。
补一句。同时开两种压缩模块时顺序很关键,宁可只留一种,也不要把编码声明交给两层去拼。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
