1. 课程导入与性能问题定位

在开始讨论 HTTP/2 与 HTTP/3 的具体优化手段之前,我们需要先建立一个共同的判断框架:什么样的页面才算“慢”,慢在哪里,以及优化到什么程度才算达标。如果缺少这个框架,后续的服务器推送、多路复用、QUIC 迁移等配置很容易变成“为了用而用”,既无法解释收益,也无法定位回退。

一、HTTP/2 与 HTTP/3 到底在优化什么

HTTP/1.1 的核心限制在于:一个 TCP 连接在同一时刻只能处理一个请求-响应事务,浏览器为了并发只能开启 6 个左右的连接,于是出现队头阻塞、连接竞争和重复握手。HTTP/2 的优化目标是在单条 TCP 连接上通过二进制分帧和流(Stream)实现多路复用,让多个请求并行交错传输,同时用 HPACK 压缩头部、用服务器推送提前下发资源。HTTP/3 则把传输层从 TCP 换成基于 UDP 的 QUIC,把“连接级队头阻塞”进一步消除:某条流丢包不会阻塞其他流,并且 0-RTT/1-RTT 握手让首字节时间更短。

因此,两者的优化目标可以归纳为三条主线:降低延迟(尤其是首字节时间 TTFB 与首屏时间)、提升吞吐(单位时间传输的有效字节数)、提高连接复用率(减少握手与连接建立开销)。这三条主线并不是并列的,而是相互制约:连接复用率越高,握手开销越低,但单连接上的流竞争也可能推高尾延迟。

HTTP/2 与 HTTP/3 性能定位关系图 从协议能力 → 核心指标 → 业务瓶颈 → 优化动作的因果链 HTTP/2 能力 • 二进制分帧 / 多路复用 • HPACK 头部压缩 • 服务器推送 / 流优先级 • 单 TCP 连接承载多流 HTTP/3 能力 • QUIC over UDP • 流级独立重传 • 0-RTT / 1-RTT 握手 • 连接迁移(IP 变化不断连) HTTP/1.1 瓶颈 • 每连接单请求事务 • 6 连接并发上限 • 头部重复传输 • TCP 队头阻塞 核心指标层 延迟:TTFB / FCP / LCP 吞吐:有效载荷 / 总字节 连接复用率:请求数 / 连接数 真实业务瓶颈识别 首屏资源串行依赖 · 大图未压缩 · 跨域多连接 · 弱网丢包 · 服务端 TTFB 偏高 优化动作:启用 H2/H3 · 资源合并与预加载 · 连接收敛 · 弱网调优

二、三个核心指标的测量口径

要让优化可验证,指标必须有明确口径。延迟方面,TTFB 指从发起请求到收到响应第一个字节的时间,它主要反映服务端处理与网络往返;FCP(首次内容绘制)和 LCP(最大内容绘制)反映用户实际感知的渲染速度。吞吐方面,建议区分“总传输字节”和“有效载荷字节”,因为 HTTP/2 的头部压缩会让总字节下降,但若资源本身未压缩,有效载荷占比仍然很低。连接复用率则用“页面请求总数 ÷ 实际建立的连接数”衡量,HTTP/1.1 下这个值通常接近 6,而 HTTP/2 下理想情况可以接近 1。

一个常见的误区是只看平均值。真实业务中,P95 和 P99 延迟往往由少数弱网用户或大资源请求决定。例如某电商首页在 4G 网络下平均 LCP 为 2.1s,但 P95 达到 5.8s,进一步分析发现是首屏一张 1.2MB 的未压缩 Banner 图在丢包环境下重传多次。这类问题在平均值里被掩盖,却直接影响转化率。

三、真实业务中的瓶颈识别方法

识别瓶颈建议按“先分层、再定位、后验证”的顺序推进。第一步用浏览器 DevTools 的 Network 面板查看瀑布图:如果多个请求呈阶梯状串行排列,说明存在资源依赖链;如果同一域名下出现大量“Queueing”或“Stalled”,说明连接数受限。第二步用 chrome://net-export 或服务端日志确认协议版本与连接复用情况。第三步在弱网条件下复测,观察丢包对延迟的影响。

下面是一段可直接用于采集连接复用率的示例脚本,它通过 Performance API 统计请求数与连接建立次数:

// 在页面加载完成后执行,统计连接复用率
const entries = performance.getEntriesByType('resource');
const requestCount = entries.length;
// 通过 transferSize 与 encodedBodySize 估算有效载荷占比
let totalTransfer = 0, totalEncoded = 0;
entries.forEach(e => {
  totalTransfer += e.transferSize || 0;
  totalEncoded += e.encodedBodySize || 0;
});
const payloadRatio = totalEncoded / totalTransfer;
console.log('请求总数:', requestCount);
console.log('有效载荷占比:', payloadRatio.toFixed(3));
// 连接复用率需结合服务端日志或 net-export 中的 socket 数计算

需要说明的是,上述脚本只能给出请求侧数据,连接数需要结合服务端或 net-export 才能得到准确值。示例中的数值均为教学假设,实际项目应以真实采集为准。

四、优化目标如何设定

设定目标时建议采用“基线 + 目标 + 回退阈值”的方式。例如某内容站基线为:TTFB 380ms、LCP 2.6s、连接复用率 5.8。启用 HTTP/2 后目标设为 TTFB ≤ 300ms、LCP ≤ 2.0s、连接复用率 ≥ 0.9;若 LCP 反而超过 2.8s,则触发回退检查。回退检查应优先排查:是否因单连接流竞争导致大资源阻塞小资源、是否服务器推送了不需要的资源、是否 TLS 握手开销抵消了复用收益。

定位性能问题时,先确认协议版本是否真正生效。部分 CDN 或反向代理默认回退到 HTTP/1.1,表面启用了 HTTP/2,实际仍在用 6 连接并发。可用 curl -I --http2 https://example.com 查看响应头中的协议标识。
不要在没有基线数据的情况下直接开启 HTTP/3。QUIC 在部分企业网络或老旧设备上可能被 UDP 限速,导致延迟反而升高。建议先在小流量灰度中对比 P95 延迟与错误率,再决定是否全量。