第一次用 56 K「小猫」拨号上网吗?点开一张图片都要等十几秒。二十多年过去,今天的网页动辄上百个资源,却依然能做到秒开。秘诀就藏在 HTTP 协议的三次大升级里。
一、HTTP/1.0
sequenceDiagram
rect rgb(191,155,248)
客户端->服务器: TCP三次握手,建立连接
end
rect rgb(196,223,252)
客户端->>服务器: 请求
服务器->>客户端: 响应
end
rect rgb(191,155,248)
客户端->服务器: TCP四次挥手,销毁连接
end
rect rgb(191,155,248)
客户端->服务器: TCP三次握手,建立连接
end
rect rgb(196,223,252)
客户端->>服务器: 请求
服务器->>客户端: 响应
end
rect rgb(191,155,248)
客户端->服务器: TCP四次挥手,销毁连接
end
痛点:用完即焚的 TCP
- 每发一次请求,浏览器都要和服务器「握手---挥手」走完全程:
三次握手 → 发请求 → 收响应 → 四次挥手。 - 页面里 20 张图片?那就重复 20 次。
- 更惨的是「队头阻塞」:前一个请求卡住了,后面所有请求都得排队。
结果就是慢、浪费、带宽空转。
二、HTTP/1.1
sequenceDiagram
rect rgb(191,155,248)
客户端->服务器: TCP三次握手,建立连接
end
rect rgb(196,223,252)
客户端->>服务器: 请求
服务器->>客户端: 响应
客户端->>服务器: 请求
服务器->>客户端: 响应
end
rect rgb(191,155,248)
客户端->服务器: TCP四次挥手,销毁连接
end
1. 长连接(Keep-Alive)
请求头带上 Connection: keep-alive
,TCP 不再用完就关,而是"先别挂电话,我等会儿还有事"。
2. 管道化(Pipelining)
浏览器可以不等上一个响应回来,就连续发多个请求。
可惜服务器必须按顺序回包------一旦某个包慢,后面的响应全部堵死,这就是队头阻塞。
3. 曲线救国
为了"并行",前端工程师把图片、CSS、JS 扔到不同域名,浏览器一口气开 6 条 TCP 连接,硬是靠"多开几条车道"缓解堵车。
三、HTTP/2

HTTP/2 不再用文本,而是把所有数据切成二进制帧。每个帧都带一个"车牌号"(流 ID),告诉接收端"我属于哪一次请求"。
核心特性
- 多路复用
同一根 TCP 里可以交错跑无数条"流",谁先准备好谁先回,彻底解决队头阻塞。 - 头部压缩(HPACK)
把重复的 Cookie、User-Agent 等字段压缩成索引,省掉 50% 以上体积。 - 服务器推送
服务端猜你接下来要app.css
,于是提前把帧推过来,浏览器省一次往返。
结果:单连接也能跑满带宽,前端再也不用"域名散列"这种黑魔法。
四、HTTP/3
HTTP/2 再快,也救不了 TCP 的"老寒腿":三次握手慢、拥塞控制保守、任何丢包都会阻塞整个管道。
于是 HTTP/3 直接把底层换成 QUIC ------ 基于 UDP 的可靠传输协议。
QUIC 带来的变化
- 0-RTT 建链
以前需要 1.5 ~ 2 个 RTT 才能发数据,QUIC 在首次连接后把参数缓存下来,下次直接发应用数据。 - 内建多路复用
每个流独立编号、独立重传,丢包只影响一条流,不再"一人感冒全家吃药"。 - 连接迁移
手机从 4G 切到 Wi-Fi,QUIC 的 CID(连接标识)让你"换网不换链",下载继续跑。
五、总结
HTTP/1.0 短连接 单车道 堵车
HTTP/1.1 长连接 6 车道 顺序放行
HTTP/2 单 TCP 多车道 无顺序
HTTP/3 单 QUIC 多车道 无顺序 + 丢包不堵车
从"写完就撕"的 1.0,到"拆帧并行"的 2,再到"换引擎"的 3,HTTP 的每一次升级都在回答同一个问题:如何让数据更快、更稳、更安全地到达用户。