HTTP3:甩掉TCP、TCL包袱 构建高效网络|浏览器篇
# HTTP3:甩掉TCP、TCL包袱 构建高效网络
30 秒速记
HTTP/2在单个TCP连接上并发承载多个请求,减少了HTTP/1.1为并行下载建立多条连接的需求。- 多路复用提高带宽利用率,并减少重复经历
TCP慢启动的代价;头部压缩和服务器推送也是原文列举的能力。 HTTP/2解决的是HTTP/1.1的应用层队头阻塞,但底层仍受TCP按序交付约束。- 单连接提升了正常网络下的传输效率,也扩大了底层丢包的影响范围:一个包未到达时,多路请求都会等待。
HTTP/3的出现并非因为HTTP/2的应用层设计失效,而是为了继续处理其底层传输协议带来的限制。
HTTP/2 用一条 TCP 连接并发承载多个请求,解决了 HTTP/1.1 的应用层队头阻塞,但没有摆脱 TCP 的传输限制。 多路复用让不同请求的帧交错发送,共享已经增长的拥塞窗口,同时还支持头部压缩和服务器推送。正常网络下,这能减少多连接和重复慢启动的成本;一旦底层丢包,多个流却会一起等待。HTTP/3 因此把多流思想放到 QUIC 上,重点是缩小单个流丢包对其他流的影响。
前面两篇文章我们分析了 HTTP/1 和 HTTP/2,在 HTTP/2 出现之前,开发者需要采取很多变通的方式来解决 HTTP/1 所存在的问题,不过 HTTP/2 在 2018 年就开始得到了大规模的应用,HTTP/1 中存在的一大堆缺陷都得到了解决。
HTTP/2 的一个核心特性是使用了多路复用技术,因此它可以通过一个 TCP 连接来发送多个 URL 请求。多路复用技术能充分利用带宽,最大限度规避了 TCP 的慢启动所带来的问题,同时还实现了头部压缩、服务器推送等功能,使得页面资源的传输速度得到了大幅提升。在 HTTP/1.1 时代,为了提升并行下载效率,浏览器为每个域名维护了 6 个 TCP 连接;而采用 HTTP/2 之后,浏览器只需要为每个域名维护 1 个 TCP 持久连接,同时还解决了 HTTP/1.1 队头阻塞的问题。
从目前的情况来看,HTTP/2 似乎可以完美取代 HTTP/1 了,不过 HTTP/2 依然存在一些缺陷,于是就有了 HTTP/3。和通常一样,介绍 HTTP/3 之前,我们先来看看 HTTP/2 到底有什么缺陷。
原理拆解: HTTP/2 把请求拆成带有流标识的帧,不同流的帧可以交错写入同一个 TCP 连接。假设页面同时请求 HTML、CSS 和图片,调度器不必等图片完整发送后才发送 CSS;连接也只需维护一套拥塞窗口,已增长的发送能力可由所有流共享。头部压缩还能减少重复的请求头字段,但这些能力都位于 TCP 之上。
最小验证: 输入同一站点的两个请求,使用支持 HTTP/2 的 curl 并行发送;要验证的结论是两个传输可复用同一连接,而不是依次等待应用层响应。命令中的地址需替换为明确支持 HTTP/2 的测试站点。
curl --version
curl --http2 --parallel --parallel-immediate \
-o /dev/null -sS -w '%{url_effective} %{http_version}\n' \
'https://example.com/' \
'https://example.com/?asset=style.css'
第一行用于确认当前 curl 是否包含 HTTP2 特性;后两项并行提交请求。服务端协商成功时,两行输出中的协议版本应为 2。若显示 1.1,只能说明本次协商、服务端或本机工具未启用 HTTP/2,不能据此否定多路复用机制。
边界与排查: 单连接并不必然在所有网络中更快:连接级丢包会让全部流等待 TCP 补齐缺口;服务端并发上限、请求优先级和资源大小也会影响结果。工程上应在浏览器网络面板中检查 Protocol、连接标识和瀑布图,并结合不同延迟、丢包条件下的首字节时间与页面完成时间判断收益。HTTP/3 保留多流思想,但把传输建立在 QUIC 上,以缩小单个流丢包对其他流的牵连。
面试官追问
追问 1首页有 80 个小资源,性能评审仍建议把静态文件拆到 6 个域名,以复用 HTTP/1.1 的并行下载经验;当前已协商为 HTTP/2,你会同意吗?
不能直接沿用域名分片,因为 HTTP/2 可让多个流复用一个持久 TCP 连接,并共享已经增长的拥塞窗口。额外域名可能重新引入多连接建立与慢启动成本;是否保留分片仍应结合真实协议、连接标识和瀑布图验证。
追问 2你要验证同站点的 HTML 与 CSS 是否真正使用 HTTP/2 多路复用,只看到两个请求同时完成还不够,工程上会检查什么?
应先确认客户端支持 HTTP2,再检查协商出的协议版本、连接标识以及请求瀑布图,判断两个请求是否共享同一连接。并行完成只能说明表象,若工具输出 1.1,还需排查服务端、协商链路或本机能力,不能据此否定机制。
追问 3同一套页面从稳定网络迁到高延迟、易丢包的移动链路后,HTTP/2 单连接反而拖慢全部资源,你如何解释这种约束变化?
HTTP/2 的多个流虽然在应用层独立,却共同建立在同一个按序交付的 TCP 连接上。底层数据包丢失时,所有流都可能等待缺口重传,因此带宽充足也无法消除连接级队头阻塞;应结合丢包条件下的时序数据判断。
追问 4线上首屏偶发卡住,网络面板显示 CSS、图片和接口都走同一条 HTTP/2 连接并同时停顿,但服务器 CPU 正常,你会优先排查哪些信号?
应优先关联连接级丢包、重传和延迟变化,确认是否由 TCP 补齐缺口导致全部流等待。随后检查服务端并发上限、请求优先级和资源大小,结合首字节与页面完成时间复现;仅看服务器 CPU 无法定位传输层阻塞。
追问 5网关团队认为 HTTP/2 已有多路复用,没有升级 HTTP/3 的必要;弱网用户却持续出现单次丢包拖住全部请求,你怎么做方案取舍?
推动 HTTP/3 的依据不是重复实现多路复用,而是将多流传输建立在 QUIC 上,缩小单个流丢包对其他流的牵连。迁移仍需验证实际协商、网络条件和页面指标,不能仅凭协议名称断言更快;服务端限制与资源调度也会继续影响结果。
追问 6前端同学把 HTTP/2 的应用层队头阻塞缓解理解成“网络层再也没有队头阻塞”,你会怎样把它与 HTTP/3 串起来?
HTTP/2 允许不同流的帧交错发送,解决了请求必须按应用层响应顺序排队的问题,但这些帧仍由同一条 TCP 连接按序交付。HTTP/3 保留多流思想并改用 QUIC,目标之一正是降低单流丢包牵连其他流的范围。
# TCP 的队头阻塞
30 秒速记
TCP将数据拆成有序数据包,并要求接收端按发送顺序恢复和交付数据。- 某个数据包丢失时,即使后续包已经到达,也要等待缺失包重传;这就是传输层的队头阻塞。
HTTP/2的多个数据流共享一个TCP连接,因此任一路对应的底层包丢失,都可能暂停该连接上的全部请求。HTTP/1.1通常使用多条TCP连接,单条连接阻塞时其他连接仍可传输;它以更多连接成本换取故障影响隔离。- 丢包率升高会削弱
HTTP/2单连接复用的收益;原文引用的测试称丢包率达到2%时HTTP/1.1可能更快,但该数值仅适用于相应测试条件。
TCP 队头阻塞是指前面的数据包丢失后,后续包即使已经到达,也必须等待缺失包重传才能按序交付。 HTTP/2 的多个流复用同一条 TCP 连接,所以一次丢包可能让连接上的全部请求暂停。相比之下,HTTP/1.1 常用多条连接,一条被阻塞时其他连接还能传输,但代价是更多握手和拥塞控制成本。原文提到丢包率达到 2% 时 HTTP/1.1 可能更快,不过这是特定测试结果,不能当作固定分界线。
