5.2 压缩与HTTP/2


文档摘要

5.2 压缩与 HTTP/2 本节摘要:响应归途的第二道工序是"瘦身与提速"。压缩用 CPU 换带宽——文本类内容通常能缩到三分之一以下,但压错对象(已压缩的图片视频)会白烧 CPU;HTTP/2 用单连接多路复用消灭了 HTTP/1.1 时代的"排队等待",但要它在 httpd 上生效,有一个必须满足的前提。本节给出可直接落地的压缩配置、排除清单、验证命令,以及 HTTP/2 的启用方法与实测对比。 学习目标 阅读完本节,你应当能够: 配置 moddeflate 并解释每个压缩级别与类型的取舍; 列出"不该压缩"的内容类型并说明原因; 验证响应是否真的被压缩; 在 httpd 上启用 HTTP/2 并理解其前提条件; 解释多路复用解决了 HTTP/1.1 的什么病。

5.2 压缩与 HTTP/2

本节摘要:响应归途的第二道工序是"瘦身与提速"。压缩用 CPU 换带宽——文本类内容通常能缩到三分之一以下,但压错对象(已压缩的图片视频)会白烧 CPU;HTTP/2 用单连接多路复用消灭了 HTTP/1.1 时代的"排队等待",但要它在 httpd 上生效,有一个必须满足的前提。本节给出可直接落地的压缩配置、排除清单、验证命令,以及 HTTP/2 的启用方法与实测对比。

学习目标

阅读完本节,你应当能够:

  1. 配置 mod_deflate 并解释每个压缩级别与类型的取舍;
  2. 列出"不该压缩"的内容类型并说明原因;
  3. 验证响应是否真的被压缩;
  4. 在 httpd 上启用 HTTP/2 并理解其前提条件;
  5. 解释多路复用解决了 HTTP/1.1 的什么病。

压缩的账:CPU 换带宽

gzip 对 HTML、CSS、JS、JSON 这类文本内容的压缩率通常在 65%–80%——一个 100KB 的页面压到 25KB,对慢速移动网络用户是质变。代价是服务器 CPU 与一点点延迟(攒够缓冲再压)。这笔账在现代硬件上几乎总是划算:压缩 25KB 的开销远小于多传 75KB 的时间。

配置(需要 mod_deflate,发行版普遍默认加载):

# 只压文本类:已压缩格式压不动还白费CPU AddOutputFilterByType DEFLATE text/html text/plain text/css AddOutputFilterByType DEFLATE application/javascript application/json AddOutputFilterByType DEFLATE application/xml text/xml image/svg+xml # 老浏览器的兼容排除(现代环境基本可省) BrowserMatch \bMSIE\s[1-6] no-gzip dont-vary

排除清单比压缩清单更重要:png、jpg、webp、woff2、mp4 这些格式在生成时已经做过专门压缩,gzip 再压一遍的收益接近零,CPU 却照付。上面配置按 MIME 类型白名单压缩,天然排除了它们——比按"全部压"再打补丁排除的写法安全。

两个进阶取舍。压缩级别:deflate 默认级别(约 6)是吞吐与压缩率的平衡点,对文本类内容调高级别收益递减,一般不动。动态与静态内容:动态内容每个响应现场压;静态文件如果占比极高,可以用预压缩方案——提前生成 .gz 文件让服务器直接发送(mod_brotli/mod_deflate 的预压缩支持),CPU 开销归零,代价是多一道构建工序。

验证压缩真的生效:

# -H 声明接受压缩,响应头应有 Content-Encoding: gzip curl -sI -H "Accept-Encoding: gzip" https://www.example.com/ | grep -iE "content-encoding|vary" # 预期: # Content-Encoding: gzip # Vary: Accept-Encoding

Vary: Accept-Encoding 这行常被忽略却至关重要:它告诉中间缓存"这份响应因压缩能力而不同",缺了它,CDN 可能把 gzip 版本发给不支持压缩的客户端。

HTTP/1.1 的老病:连接不够用

要看懂 HTTP/2 的价值,先回顾 HTTP/1.1 的三个顽疾。队头阻塞:同一连接上请求必须逐个处理,前一个慢了后面全堵。并发靠连接数堆:浏览器只能给每域名开约 6 个连接,超过就得排队,开发者被迫做域名分片、雪碧图、内联资源这些"对抗协议"的工程技巧。头部冗余:每个请求都完整重复几十上百字节的相同头,移动网络下浪费可观。

HTTP/2 的三剂药:二进制分帧(请求拆成帧传输,解析更快更稳);单连接多路复用(一条连接上交错传输多个请求的帧,互不阻塞);头部压缩(重复头只传差量)。工程上最直接的红利是:域名分片、雪碧图这些老技巧全部可以退休。

在 httpd 上启用 HTTP/2

关键前提先说:httpd 的 HTTP/2 实现(mod_http2)只对 event MPM 完整支持——又一个"早该离开 prefork"的理由。其次,主流浏览器只在加密连接上使用 HTTP/2,所以实用形态是"HTTPS + HTTP/2"(协议本身并不强制加密)。

配置出奇地简单:

LoadModule http2_module modules/mod_http2.so # 在 HTTPS 虚拟主机里(通常是全局或默认站点级) Protocols h2 http/1.1

一行 Protocols 即完成协商:支持 h2 的客户端用 HTTP/2,其余退回 1.1。明文端口想用 h2c 的场景(内部调试)可以写 Protocols h2c http/1.1,但浏览器不支持,实用价值限于服务间通信。

验证:浏览器开发者面板的协议列显示 h2;或命令行直查:

curl -sI --http2 https://www.example.com/ | head -1 # 预期:HTTP/2 200

图 5-2 HTTP/1.1 与 HTTP/2 传输形态对比

图 5-2 HTTP/1.1 与 HTTP/2 传输形态对比

压缩与 HTTP/2 的交点

两者叠加时有两个注意点。头部压缩不等于内容压缩:HTTP/2 的头部压缩只作用于请求头,响应正文的 gzip 依然要靠 mod_deflate,两者并行不悖、都要开。别在 HTTP/2 下做域名分片:分片的本意是多开连接绕开 1.1 的六连接限制,在 h2 下反而破坏单连接复用,把优化做成了负优化——迁移 h2 时记得把历史分片域名收回。

最后一个现实提醒:HTTP/2 不是银弹。它解决的是"同域多资源的排队",不能替你解决后端慢、图片过大、缓存缺失——协议层的收益在整条链路里通常是一到两成,剩下的还在第 5.1 节的缓存与后端容量里。

⚠️ 常见坑:开了 mod_http2 却发现客户端仍在用 1.1。按顺序查三样:虚拟主机里 Protocols 写了吗(写错作用域等于没写);MPM 是 event 吗;连接是 HTTPS 吗。三关全过,h2 自然出现。

本节要点回顾

  • 压缩白名单:只压文本类,已压缩格式(图片、woff2、视频)绝不压,按类型白名单实现;
  • Vary 头:Accept-Encoding 的 Vary 缺失会让 CDN 送错版本,验证时一起查;
  • 预压缩:静态大户可预生成压缩文件,CPU 开销归零;
  • HTTP/2 三剂药:二进制分帧、多路复用、头部压缩,队头阻塞与六连接上限成历史;
  • 启用三前提:event MPM、TLS、Protocols 指令写在正确作用域;
  • 迁移清障:收回域名分片与雪碧图等"对抗 1.1"的历史技巧。

💡 一句话记住本节:压缩是给行李减重,HTTP/2 是把六条单车道并成一条八车道——都做,才快。

下一节给这条路装上锁:HTTPS 与 TLS。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U