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 与首屏时间)、提升吞吐(单位时间传输的有效字节数)、提高连接复用率(减少握手与连接建立开销)。这三条主线并不是并列的,而是相互制约:连接复用率越高,握手开销越低,但单连接上的流竞争也可能推高尾延迟。
二、三个核心指标的测量口径
要让优化可验证,指标必须有明确口径。延迟方面,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 握手开销抵消了复用收益。
curl -I --http2 https://example.com 查看响应头中的协议标识。