← 返回题目列表

HTTP 压缩是怎么提升性能的?gzip、br、deflate 有什么区别?

高频 中等 第 10 / 27 题 更新于 2026/08/01
HTTP压缩gzipBrotlibr性能优化

简化版

HTTP 压缩通过减少响应体字节数来降低传输时间,客户端用 Accept-Encoding 声明支持的算法,服务端用 Content-Encoding 返回实际压缩方式。gzip 兼容性最好,Brotli(br)压缩率通常更高,适合 HTTPS 下的文本资源;图片、视频、zip 这类已压缩内容通常不再压缩。压缩能省带宽,但会消耗 CPU,并且要注意缓存、Vary 头和小文件收益。

详细版

典型协商过程:

GET /app.js HTTP/1.1
Accept-Encoding: br, gzip

HTTP/1.1 200 OK
Content-Encoding: br
Vary: Accept-Encoding

压缩最适合 HTML、CSS、JavaScript、JSON、SVG 这类文本内容。一个 500 KB 的 JS 文件,用 gzip 可能变成 150 KB,用 Brotli 可能变成 120 KB;在 10 Mbps 网络下,传输时间从约 400 ms 降到约 96 ms,收益明显。但压缩也要花 CPU,动态响应压缩等级过高可能拖慢服务端。

面试要点包括:客户端和服务端如何协商;为什么要设置 Vary: Accept-Encoding;哪些资源不适合压缩;动态压缩和静态预压缩怎么选;为什么 HTTPS 场景下更常见 Brotli。

完整版教学

一、HTTP 压缩优化的是传输字节数

网络传输时间大致受响应大小和可用吞吐影响。响应越小,下载越快,链路拥塞概率也更低。HTTP 压缩就是在服务端发送前把响应体压缩,客户端收到后解压再使用。对文本资源来说,重复字符串、字段名、空格和代码模式很多,压缩率通常很好。

例如一个 JSON 响应里反复出现 "user_id""created_at",gzip 能把这些重复模式编码成更短表示。假设响应从 100 KB 压到 25 KB,在 5 Mbps 有效吞吐下,传输时间约从 160 ms 降到 40 ms。

100 KB * 8 / 5 Mbps ≈ 160 ms
25 KB  * 8 / 5 Mbps ≈ 40 ms

压缩不是让网络 RTT 变小,而是让需要传的字节更少。

二、Accept-Encoding 和 Content-Encoding 如何协商

客户端通过 Accept-Encoding 告诉服务端自己支持哪些压缩算法。服务端选择一种支持的算法压缩响应,并通过 Content-Encoding 告诉客户端如何解压。如果服务端不压缩,就不返回该响应头或返回 identity。

Accept-Encoding: br, gzip, deflate
Content-Encoding: gzip

注意 Content-Encoding 描述的是响应体编码,不是资源原始类型。Content-Type: application/json 表示解压后是 JSON;Content-Encoding: gzip 表示传输时被 gzip 压缩。

三、gzip、deflate 和 Brotli 的区别

gzip 是最常见的通用压缩格式,兼容性极好。deflate 历史上存在实现差异,实际 Web 优化里不如 gzip 常用。Brotli 的压缩率通常更高,尤其适合静态文本资源,但压缩开销可能更大,动态高等级压缩要谨慎。

算法特点常见使用
gzip兼容最好,速度和压缩率均衡动态和静态文本
deflate历史兼容坑较多较少主动选择
br压缩率更高,HTTPS 下主流浏览器支持静态资源、文本 API

Brotli 常用于 HTTPS,因为主流浏览器通常只在安全上下文里发送 br 支持。工程里常见做法是构建阶段预生成 .br.gz 静态文件,由 Nginx/CDN 直接返回,避免运行时重复压缩。

四、哪些资源不应该压缩

已经压缩过的资源通常不适合再压缩,例如 JPEG、PNG、WebP、MP4、PDF、zip、gzip 文件。再次压缩收益很小,甚至可能变大,还会浪费 CPU。特别小的响应也不一定值得压缩,因为压缩头和 CPU 开销可能超过收益。

资源类型是否适合压缩原因
HTML/CSS/JS适合文本重复多
JSON/SVG适合字段和标签重复
JPEG/WebP/MP4不适合已压缩
小于 1 KB 响应视情况收益有限

很多服务器会设置最小压缩大小,例如 gzip_min_length 1024,避免对很小响应做无意义压缩。

五、压缩等级是 CPU 和体积的权衡

压缩等级越高,通常体积越小,但 CPU 消耗越大。动态 API 如果每个请求都用最高等级 Brotli,可能省了几 KB 带宽,却让 CPU 飙高、TTFB 变慢。静态资源可以在构建阶段慢慢压,动态响应要选择中等等级。

假设某 JSON:

策略压缩后大小压缩耗时
gzip level 132 KB1 ms
gzip level 627 KB4 ms
br level 1122 KB80 ms

如果是静态 JS 文件,80 ms 构建时花掉没关系;如果是接口实时响应,80 ms 会直接增加用户等待。

六、缓存必须处理 Vary

同一个 URL 对不同客户端可能返回不同编码版本。支持 br 的客户端拿 br,不支持的拿 gzip 或未压缩。如果缓存系统不区分 Accept-Encoding,可能把 br 响应给不支持 br 的客户端,导致乱码或解压失败。

因此服务端应返回:

Vary: Accept-Encoding

这表示缓存键要把 Accept-Encoding 纳入考虑。CDN、反向代理、浏览器缓存都需要据此区分不同压缩版本。面试中提到 Vary,说明你考虑到了真实部署链路。

七、压缩和安全也有关系

压缩会让响应大小和内容相关,在某些场景可能引入侧信道风险。历史上的 BREACH 攻击就利用了“攻击者可控输入 + 响应中有 secret + 响应压缩后长度可观测”的条件推测敏感信息。普通静态资源没有这个问题,但含 CSRF Token、密钥片段的动态页面要谨慎。

风险条件可以这样记:

可控输入 + 同响应里包含 secret + 压缩 + 可观察长度 = 风险组合

解决思路包括避免把用户可控内容和 secret 放在同一压缩上下文、对敏感响应关闭压缩、使用随机填充等。

八、常见误区与追问

  • 误区:开启压缩一定提升性能。 文本大响应通常收益明显,但小响应或已压缩资源可能收益很低,还会增加 CPU。
  • 误区:Content-Encoding 和 Content-Type 是一回事。 前者表示传输编码,后者表示解压后的媒体类型。
  • 误区:Brotli 永远比 gzip 更好。 Brotli 压缩率高,但动态高等级压缩 CPU 成本可能不划算。
  • 误区:CDN 缓存不用关心压缩。 必须处理 Vary: Accept-Encoding,否则可能返回客户端不支持的编码。
  • 追问:为什么图片视频不建议再压缩? 它们通常已经使用专门算法压缩,再压缩收益小且浪费 CPU。
  • 追问:静态资源如何高效使用 Brotli? 构建阶段预压缩生成 .br,由 CDN/Nginx 按客户端能力直接返回。
  • 追问:压缩会不会有安全风险? 动态敏感响应可能受长度侧信道影响,需要避免 secret 和可控输入共享压缩上下文。

九、加强记忆

HTTP 压缩按“客户端声明 Accept-Encoding,服务端返回 Content-Encoding,缓存用 Vary 区分版本”来记。gzip 兼容,br 压缩率高,文本资源收益大,图片视频通常别压。动态压缩要权衡 CPU 和 TTFB,静态资源优先预压缩,敏感动态页面还要注意压缩侧信道风险。