nginx的brotli与https协同需三者并重:https建立可信通道(仅https下浏览器才发br请求)、brotli在边缘和源站全链路生效(含proxy_set_header与brotli_static)、缓存键必须包含$http_accept_encoding以避免污染。

要让 Nginx 的 Brotli 压缩和 HTTPS 证书配置真正协同工作,实现端到端高效加密传输,关键不是“开了 Brotli 就自动变快”,而是把三件事串通:HTTPS 建立可信加密通道、Brotli 在传输链路各环节正确协商与生效、缓存系统不搞混不同编码版本。缺一不可。
HTTPS 是 Brotli 协商的前提
现代浏览器只在 HTTPS 下才发送 Accept-Encoding: br 请求头。HTTP 明文连接中,Brotli 不会被触发——这是硬性限制,不是配置问题。
- 确保站点已部署由 Let’s Encrypt 或其他可信 CA 签发的有效证书,且域名解析、443 端口开放、系统时间准确
- Nginx 的
server块必须启用 SSL 并明确支持 TLS 1.2/1.3:listen 443 ssl http2;ssl_protocols TLSv1.2 TLSv1.3; - 不要仅满足于“能打开 HTTPS”,还要验证浏览器地址栏显示锁形图标、无证书警告,并确认响应头含
Strict-Transport-Security(HSTS)
Brotli 必须在回源链路中真实传递
边缘 Nginx 启用 brotli on 只影响它发给浏览器的内容;若后端(源站)仍是 HTTP 或未返回 Brotli 编码,那整个链路的压缩收益就断在了中间。
- 在反向代理的
location块中强制带上编码偏好:proxy_set_header Accept-Encoding "br,gzip,deflate";(注意br放最前) - 源站 Nginx 必须加载
ngx_http_brotli_filter_module,并开启:brotli on;brotli_types text/css application/javascript application/json; - 更推荐源站启用
brotli_static on;,配合预压缩好的.br文件,避免实时压缩 CPU 开销
缓存键必须区分编码类型
如果所有请求(带 br / 带 gzip / 无压缩)都存进同一个缓存 key,就会出现“缓存污染”:用户请求 Brotli,却拿到之前缓存的 Gzip 内容,导致浏览器解压失败报错。
- 修改
proxy_cache_key,显式加入编码标识:proxy_cache_key "$scheme$request_method$host$request_uri$http_accept_encoding"; - 不建议混入
$http_user_agent或其他高基数变量,否则缓存碎片化严重,命中率暴跌 - 只要 accept-encoding 实际只有
br、gzip、空三种情况,这个变量就足够精准区分
验证是否真走通整条链路
不能只看浏览器 Network 面板里资源“Size”小——那可能是边缘用 Gzip 压的,跟 Brotli 无关。
- 查边缘 Nginx access log,加字段
$upstream_http_content_encoding,确认值为br - 查源站 access log,确认收到的 upstream 请求头含
Accept-Encoding: br - 用 curl 直连源站对比:
curl -H "Accept-Encoding: br" -I https://origin.example.com/app.js
响应头应含Content-Encoding: br,且 body 大小小于不带该头的请求











