HTTP2:如何提升网络速度|浏览器篇
# HTTP2:如何提升网络速度
30 秒速记
HTTP/1.1的提速手段主要是复用连接、单域名并发连接和借助CDN分散资源请求。- 按原文所述的浏览器模型,单个域名最多并行维护 6 条
TCP持久连接,域名分片还能进一步增加并发通道。 - 这些优化能够缩短大量资源的总体下载时间,但本质上是在增加连接和并发,没有消除协议内部的性能瓶颈。
- 原文中的
100 × n × RTT ÷ (6 × CDN 数量)只是便于理解的理想化估算,未纳入资源大小、连接竞争和网络波动。
HTTP/1.1 主要通过持久连接、同域名多连接和 CDN 域名分片来提升资源加载速度。 持久连接减少重复建连,而浏览器为单个域名维护最多 6 条连接,再用多个域名扩展并发通道。本质上,这些手段只是用更多连接覆盖等待时间,没有解决协议内部的排队问题。资源较多时通常有收益,但多条连接仍会共享带宽并分别经历建连和慢启动,不能简单认为连接数翻倍、速度也会等比例翻倍。
上一篇文章我们聊了 HTTP/1.1 的发展史,虽然 HTTP/1.1 已经做了大量的优化,但是依然存在很多性能瓶颈,依然不能满足我们日益变化的新需求,所以就有了我们今天要聊的 HTTP/2。
本文我们依然从需求的层面来谈,先分析 HTTP/1.1 存在哪些问题,然后再来分析 HTTP/2 是如何解决这些问题的。
我们知道 HTTP/1.1 为网络效率做了大量的优化,最核心的有如下三种方式:
- 增加了持久连接;
- 浏览器为每个域名最多同时维护 6 个 TCP 持久连接;
- 使用 CDN 的实现域名分片机制。
通过这些方式就大大提高了页面的下载速度,你可以通过下图来直观感受下:

在该图中,引入了 CDN,并同时为每个域名维护 6 个连接,这样就大大减轻了整个资源的下载时间。这里我们可以简单计算下:如果使用单个 TCP 的持久连接,下载 100 个资源所花费的时间为 100 * n * RTT;若通过上面的技术,就可以把整个时间缩短为 100 * n * RTT/(6 * CDN 个数)。从这个计算结果来看,我们的页面加载速度变快了不少
原理拆解: HTTP/1.1 的持久连接减少重复握手,但同一连接上的响应通常仍需按次序完成;浏览器于是为同一域名建立多条连接,并通过不同域名或 CDN 增加并发通道。收益取决于请求数量、资源耗时和连接上限,并不能简单等同于带宽按连接数倍增:多条连接仍会共享出口带宽,还会分别经历连接建立与慢启动。
最小验证: 输入是 12 个各延迟 100ms 的本地请求,分别把客户端并发上限设为 1 和 6,验证扩大连接并发能缩短总等待时间。将代码保存为 h1.js,使用 Node.js 18+ 执行 node h1.js。
const http = require('node:http');
const { performance } = require('node:perf_hooks');
const server = http.createServer((req, res) => {
setTimeout(() => res.end('ok'), 100);
});
server.listen(0, '127.0.0.1', async () => {
const { port } = server.address();
async function run(maxSockets) {
const agent = new http.Agent({ keepAlive: true, maxSockets });
const start = performance.now();
const jobs = Array.from({ length: 12 }, (_, i) =>
new Promise((resolve, reject) => {
http.get({ host: '127.0.0.1', port, path: `/${i}`, agent }, res => {
res.resume();
res.on('end', resolve);
}).on('error', reject);
})
);
await Promise.all(jobs);
agent.destroy();
return Math.round(performance.now() - start);
}
console.log('1 connection:', await run(1), 'ms');
console.log('6 connections:', await run(6), 'ms');
server.close();
});
maxSockets 控制同一源的并发连接数;典型输出约为 1200ms 和 200ms,说明并发可覆盖服务器等待时间。该本地实验没有模拟公网握手、拥塞控制和带宽竞争,因此不能证明连接越多越快。
边界与排查: 可在浏览器开发者工具的 Network 面板查看 Protocol、Connection ID、排队时间和瀑布图;若大量时间落在 Queueing,增加并发可能有效,若主要耗时来自大文件传输或服务端处理,域名分片收益有限。使用 HTTP/2 或连接合并时,域名数量也不再等价于实际连接数量。
面试官追问
追问 1首页有 100 个小资源,产品看到 100 × n × RTT ÷ (6 × CDN 数量) 后要求把 CDN 域名翻倍,并承诺加载时间减半,你会接受吗?
不能据此承诺耗时减半,该公式只是在理想模型中表达增加并发通道后的趋势。真实请求还受资源耗时、连接建立、慢启动和共享带宽影响;域名翻倍也不代表有效吞吐会同比增长。
追问 2一个 HTTP/1.1 页面有 12 个各等待约 100ms 的本地请求,你如何用最小实验判断单连接排队是不是主要耗时?
可分别把客户端同源并发上限设为 1 和 6,比较 12 个请求全部完成的时间与瀑布图。若并发后等待明显重叠,说明增加连接能覆盖服务端等待;本地结果不包含公网握手、慢启动和带宽竞争,不能直接外推线上收益。
追问 3开发团队把资源从一个域名拆到三个 CDN 域名,但站点已经协商为 h2,仍坚持“域名越多,连接一定越多”,你怎么判断?
不能再按 HTTP/1.1 的域名分片模型直接推导连接数,因为 HTTP/2 支持多路复用和连接合并。应在开发者工具中核对 Protocol、连接标识与瀑布图;若请求共享连接,增加域名不仅未必扩充通道,还会增加配置复杂度。
追问 4线上首页仍然很慢,Network 面板显示请求几乎没有 Queueing,主要时间落在大文件下载和服务端响应,你还会增加分片域名吗?
此时不应把增加域名作为首选,因为并发通道不足并非主要证据,瓶颈更可能在大文件传输或服务端处理。应先拆分各阶段耗时并核对连接状态;继续分片会增加连接成本,也无法突破共享出口带宽。
追问 5老系统只能使用 HTTP/1.1,关键资源很多;你会在“一个域名复用持久连接”和“多个 CDN 域名增加并发”之间怎么取舍?
应根据排队时间与带宽占用决定,持久连接能减少重复握手,多域名则能扩展受限的同源并发通道。若大量小请求主要卡在排队,分片可能有效;若链路已接近带宽上限,更多连接会经历慢启动并相互竞争,收益有限甚至增加成本。
# HTTP/1.1 的主要问题
30 秒速记
HTTP/1.1的核心性能问题不是标称带宽不足,而是资源加载过程难以持续把带宽用满。- 每条新建
TCP连接都要经历慢启动,小体积的HTML、CSS和JavaScript往往在速率尚未提升时就已传输,关键渲染因此被推迟。 - 同一页面建立多条
TCP连接后,它们会竞争固定带宽,而且连接之间无法协调关键资源与普通资源的下载次序。 - 持久连接中的请求按顺序处理时,前一个请求未结束会阻塞后续请求,等待期间网络和计算资源都可能闲置。
- 队头阻塞还会延迟图片等资源的提前接收与预处理,压缩浏览器可用于解码等工作的时间窗口。
HTTP/1.1 的核心性能问题是很难持续用满带宽,关键原因包括 TCP 慢启动、多连接竞争和队头阻塞。 小型 HTML、CSS、JavaScript 可能在连接尚未提速时就传完,从而推迟首次渲染。页面同时建立多条连接后,它们既要争抢固定带宽,又无法统一协调关键资源的优先级。持久连接上的慢请求还可能挡住后续请求,不过服务端响应慢或请求存在依赖时,不能一概归因于协议队头阻塞。
