2. HTTP/1.1的工程局限复盘

HTTP/1.1 在 1997 年定稿时,Web 页面平均只有十几个资源。二十多年后,一个典型现代前端页面动辄加载 80~150 个请求:HTML、CSS、几十个 JS chunk、字体、图片、埋点、A/B 实验脚本。协议本身没变,但负载形态彻底变了。HTTP/1.1 的三个结构性缺陷——队头阻塞、并发连接数限制、头部冗余——正是在这种量级差异下被放大成工程瓶颈的。理解它们,才能理解 HTTP/2 为什么要引入二进制分帧、多路复用和 HPACK。

一、队头阻塞:一条连接上的串行代价

HTTP/1.1 的“持久连接”(keep-alive)允许在一条 TCP 连接上连续发送多个请求,但请求与响应必须严格按序。也就是说,如果第一个请求的响应迟迟不来,后面排队的请求即使服务器早已准备好,也无法被浏览器取走。这就是应用层队头阻塞(Head-of-Line Blocking,HOL Blocking)。

它的危害在“慢资源”场景下最明显。假设一条连接上依次请求:/api/user(后端查库 300ms)、logo.png(静态 5ms)、app.js(静态 8ms)。由于串行,logo 和 app.js 实际要等到 300ms 之后才开始传输,用户感知到的首屏时间被一个慢接口拖住。更糟的是,HTTP/1.1 的管线化(pipelining)理论上允许连续发请求,但响应仍须按序返回,且中间代理兼容性差,主流浏览器默认关闭,所以工程上并不能真正解决 HOL。

需要区分的是:HTTP/1.1 的 HOL 发生在应用层(请求排队),而 HTTP/2 虽然消除了应用层 HOL,却仍受 TCP 层 HOL 影响——一个丢包会让所有流等待重传。这正是 HTTP/3 改用 QUIC 的动机。本节先聚焦 HTTP/1.1 自身。

二、并发连接数限制:用“多开连接”绕过,却带来新成本

浏览器厂商的应对方式是:既然一条连接会排队,那就多开几条。RFC 7230 曾建议每个域名不超过 2 条连接,但现代浏览器普遍放宽到每域名 6 条(Chrome、Firefox 均为 6)。这带来两个工程后果:

  • 域名分片(domain sharding):把静态资源分散到 static1.example.com、static2.example.com 等多个子域,把并发上限从 6 提升到 12、18 甚至更多。代价是每个新域名都要重新 DNS 解析、TCP 三次握手、TLS 握手(若启用 HTTPS),额外 RTT 与 CPU 开销显著。
  • 连接竞争与优先级缺失:6 条连接之间没有统一调度,浏览器只能靠启发式规则决定哪个请求先发。关键 CSS 可能和低优先级埋点抢连接,导致渲染阻塞。

可以用一个简化的量化示例说明分片的收益与代价(以下为教学假设,非实测):某页面有 60 个静态资源,单域名 6 并发、每个资源平均 40ms 传输,理论串行批次为 60/6=10 批,约 400ms;若分片到 3 个域名,并发 18,批次降为 60/18≈4 批,约 160ms,看似省了 240ms。但新增 2 个域名各需 DNS(约 20ms)+ TCP(1 RTT,约 30ms)+ TLS(2 RTT,约 60ms),合计约 110ms×2=220ms 的额外握手成本,且这些握手与资源传输部分重叠。净收益被大幅压缩,甚至在高延迟移动网络下为负。这就是 HTTP/2 出现后,业界普遍建议“取消域名分片”的原因。

三、头部冗余:每个请求都在重复自己

HTTP/1.1 头部是纯文本、无状态压缩的。一个典型请求头包含 User-Agent(常 100+ 字节)、Cookie(可能数 KB)、Accept、Accept-Encoding、Referer 等。假设平均请求头 800 字节,一个页面 100 个请求,仅头部就传输约 80KB。若 Cookie 较大(如 JWT 或会话 ID),单请求头可达 2KB,总量翻倍。

更关键的是“重复”:同一页面内 100 个请求的 User-Agent、Accept、Cookie 几乎完全相同,却每次都要完整重传。在慢速上行链路(如 3G/弱网)上,头部甚至可能比响应体还大。HTTP/1.1 没有头部压缩机制,只能靠开发者手动精简 Cookie、合并请求,治标不治本。

四、迁移决策:什么时候该上 HTTP/2

HTTP/2 用二进制分帧 + 流(stream)实现单连接多路复用,用 HPACK 压缩头部,用流优先级和服务器推送(后者已逐步弃用)优化调度。它直接针对上述三个问题。但迁移不是无条件的,需要结合现状判断。

下面这张图把 HTTP/1.1 的三个瓶颈、HTTP/2 的对应机制,以及迁移决策的判断路径放在一起,便于对照。

HTTP/1.1 三大工程局限 → HTTP/2 对应机制 → 迁移决策 ① 应用层队头阻塞 • 同连接请求严格按序 • 慢响应拖住后续请求 • 管线化兼容差,默认关闭 • 首屏被慢接口绑架 ② 并发连接数限制 • 每域名约 6 条连接 • 域名分片提升并发上限 • 新增 DNS/TCP/TLS 成本 • 连接间无统一优先级 ③ 头部冗余 • 纯文本、无压缩 • UA/Cookie 每请求重传 • 100 请求 ≈ 80KB 头部 • 弱网上行压力大 二进制分帧 + 多路复用 • 请求拆为帧,流独立 • 单连接并发多流 • 消除应用层 HOL • 流优先级调度 单连接承载全部资源 • 无需域名分片 • 省去额外握手 • 连接利用率高 • 减少连接竞争 HPACK 头部压缩 • 静态表 + 动态表 • 重复头部只传索引 • 头部体积大幅下降 • 弱网收益明显 迁移决策判断 页面请求数 > 50? 是 → 收益显著 是否已用 HTTPS? 是 → 可直接协商 h2 CDN/网关支持 h2? 否 → 先升级链路 是否依赖域名分片? 是 → 迁移后应取消 弱网/移动端占比高? 是 → HPACK 收益大 灰度验证:对比 TTFB/LCP 回退方案:ALPN 降级 h1 满足 3 项以上 → 建议迁移 注:图中数值为教学示例,非实测结果;实际迁移需结合业务流量、CDN 能力与回退策略灰度验证。

决策时建议按以下顺序核对:

  1. 确认收益面:统计页面请求数与头部平均大小。若请求数长期低于 20、头部很小,HTTP/2 的边际收益有限,可暂缓。
  2. 确认前提:HTTP/2 在浏览器端几乎只通过 TLS + ALPN 协商(h2),因此 HTTPS 是事实前提。若仍是 HTTP,先完成 HTTPS 改造。
  3. 确认链路:CDN、负载均衡、反向代理(Nginx、Envoy 等)需支持 h2。Nginx 需 listen 443 ssl http2;,Envoy 需在 HttpConnectionManager 中启用 http2_protocol_options。
  4. 调整前端策略:迁移后应取消域名分片、减少雪碧图与资源合并,让多路复用发挥价值;同时保留关键 CSS 内联等首屏优化。
  5. 灰度与回退:按用户比例或地域灰度,对比 TTFB、LCP、请求成功率;保留 ALPN 降级到 HTTP/1.1 的能力,异常时可快速回退。
一个常见的误区是“上了 HTTP/2 就一定更快”。如果服务器仍按 HTTP/1.1 的思路做资源合并、域名分片,或 TLS 配置不当(如未启用会话复用),收益会被抵消。协议升级必须配合前端与服务端策略同步调整。
HTTP/2 并未解决 TCP 层队头阻塞:单个 TCP 丢包会阻塞该连接上所有流。若业务对弱网延迟极敏感,应把 HTTP/3(QUIC)纳入后续演进路线,而不是止步于 HTTP/2。