模块一:引言
HTTP(HyperText Transfer Protocol) 是基于 TCP/IP 的应用层协议,是互联网数据通信和网页传输的基石。
它采用请求-响应模式,是无状态协议,特别适合海量用户的高 并发访问场景。
HTTP 是一种请求-响应模式的协议:客户端发起请求,服务器返回响应。过程非常 简单,却极其强大——正是这种简洁性,让 HTTP 得以快速普及,成为互联网的"通用语言"。
同时,它也是无状态协议——服务器不会记得你上一次请求说了什么。每次请求都是 独立的。这种设计让它能够轻松应对海量并发访问,但也催生了 Session、Cookie、Token 等会话管理机制。
从 1991 年 HTTP 0.9 诞生至今,经历了多次重大升级。本文 将从历史演进的角度,带你系统回顾 HTTP 协议的发展脉络。
模块二:HTTP 0.9 和 HTTP 1.0 — 协议的诞生与初探
HTTP 0.9(1991年)— 一切的开始
1991年,万维网(World Wide Web)的发明者 Tim Berners-Lee 发布了 HTTP
的第一个版本。
这是一个极其简单的协议,只有一行命令:
GET /index.html
服务器直接返回 HTML 文档内容,传输完成就断开连接。
它的特点:
- 仅支持 GET 方法
- 无请求头、无响应头
- 只能传输纯 HTML 文本
- 每次请求都是一个新的 TCP 连接
现在的眼光看,HTTP 0.9 简陋得难以置信。但正是这个简单的开始,开启了互联网时代的大门。
HTTP 1.0(1996年)— 走向标准化
随着互联网蓬勃发展,HTTP 0.9 已经不够用了。1996年,HTTP 1.0 正式发布,协议开始走向标准化。
1. 多种请求方法
HTTP 1.0 扩展了请求方法:
- GET — 从服务器读取资源
- POST — 向服务器提交数据
- HEAD — 仅获取响应头,不返回正文
POST 的出现意义重大——它让表单提交成为可能,Web 开始从"只读"走向"可写"。
2. 请求头(Headers)
HTTP 1.0 创新性地引入了请求头和响应头的概念,让客户端和服务器能够传递元数据。
常用请求头:
- User-Agent — 客户端信息,比如浏览器版本、操作系统
- Cookie — 会话标识,服务端下发的会话 ID
- Content-Type — 请求体格式,比如 application/json
- Accept — 可接受的响应类型,比如 text/html, */
- Authorization — 认证信息,比如 Bearer token 或 Basic auth
User-Agent 是其中最有意思的一个。它的格式大致如下:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36
这一串标识的意思是:
- Mozilla/5.0 最初是 Netscape 浏览器的标识,后来所有浏览器都兼容这个标识
- (Macintosh; Intel Mac OS X 10_15_7) 告诉你操作系统和硬件信息
- AppleWebKit/537.36 是渲染引擎
- Chrome/146.0.0.0 是浏览器版本号
- Safari/537.36 是为了兼容 Safari
这就是为什么国内早期要区分 PC 站和移动站——不同的 User-Agent 告诉服务器你用的是什么设备,服务器就返回不同的页面。
3. 短连接
HTTP 1.0 依然是短连接模式:每次请求都要先 TCP三次握手建立连接,请求完成后四次挥手断开连接,下一次请求再重新建连。
一个网页可能有几十个资源——HTML、CSS、JS、图片、字体……每个都要单独建立和断开 TCP 连接。这种方式在当时互联网规模还不大的时候勉强够用,但随着网页资源越来越多,性能问题开始凸显。
HTTP 1.0 为协议奠定了基本框架:确立了请求-响应模式,引入了 Headers
的概念,支持多种请求方法。 但它也有很多局限:短连接效率低、无状态导致会话管理困难、明文传输不安全…… 这些问题的解决方案,都留给了下一代的 HTTP 1.1。
模块四:HTTP 2.0 — 性能飞跃
HTTP 1.1 虽然大大提升了 Web的能力,但它的核心问题——对头阻塞——始终没有解决。
2015年,HTTP 2.0发布,专门针对这个痛点进行了底层重构。
1. 二进制分帧
HTTP 1.1 的数据是明文传输的,所有数据混在一起,没有边界,没有编号,想插队 是不可能的。
举个例子:
假设浏览器同时请求:
- 流 1:index.html
- 流 3:style.css
- 流 5:app.js
HTTP 2.0 的传输可能是这样的——帧交错在一起:
流1帧头 → 流3帧头 → 流1数据 → 流5帧头 → 流3数据 → 流1数据 → ...
到达接收端之后,按流 ID 分开重组:
流1:帧1-1 + 帧1-2 + 帧1-3 → 拼成 index.html
流3:帧3-1 + 帧3-2 → 拼成 style.css
流5:帧5-1 + 帧5-2 → 拼成 app.js
为什么能解决对头阻塞?
因为每个流都有自己的 ID,独立重组。假设流 1 的某个帧丢了,只影响流1,流3和流5 照样传输、照样重组,完全不受影响。
2. 多路复用
基于二进制分帧,HTTP 2.0 实现了真正的多路复用(Multiplexing):
- 一个 TCP 连接中可以并发多个请求
- 每个请求都有一个独立的流 ID
- 帧可以交错发送,按流 ID 归类重组
举个例子:
浏览器要请求 index.html、style.css、app.js 三个资源。
HTTP 1.1 时代:
同一个域名只能开 1-6 个 TCP
连接(浏览器限制),每个请求必须等上一个响应回来才能发下一个:
TCP连接1:GET /index.html → 等 → 收到响应 → GET /style.css → 等 →
收到响应 → GET /app.js ...
TCP连接2:GET /app.js → 等 → 收到响应
...
如果 index.html 卡住了,后面 style.css 和 app.js 只能在后面排队等。
HTTP 2.0 时代:
一个 TCP 连接就够了。三个请求分属三个流,同时发送:
一个 TCP 连接里:
→ 流1: GET /index.html
→ 流3: GET /style.css
→ 流5: GET /app.js
← 流1: 返回 index.html 数据帧
← 流3: 返回 style.css 数据帧
← 流5: 返回 app.js 数据帧
三个流并行跑,互不等待,互不阻塞。
这从根本上解决了 HTTP 1.1 的对头阻塞问题。
3. 服务器推送
传统的请求模式是:浏览器请求 HTML → 服务器返回 HTML → 浏览器解析 HTML
发现需要 CSS/JS → 再去请求 CSS/JS。
HTTP 2.0 支持服务器推送(Server Push):服务器知道浏览器需要什么资源,主动把 CSS/JS 推送给浏览器,浏览器还没请求就已经收到了。
这样就省去了浏览器反复请求的延迟。
4. 头部压缩
HTTP 2.0 还对 Header 进行了压缩。因为一个请求的 Header 往往有几百字节,而实际数据可能只有几字节,Header 的开销非常大。
HTTP 2.0 使用 HPACK 算法压缩 Header,进一步减少了传输量。
HTTP 2.0 的意义
HTTP 2.0 通过二进制分帧和多路复用,从根本上解决了 HTTP 1.1 的对头阻塞问题,让 Web 性能有了质的飞跃。
但它仍然有一个隐患——底层还是 TCP。TCP 在传输层也有对头阻塞问题,一旦丢包,整个 TCP 连接上的所有流都会受影响。
这个问题的最终解决方案,就是 HTTP 3.0。
模块五:HTTP 3.0 — QUIC 革命
HTTP 2.0 虽然解决了应用层的对头阻塞,但它的底层还是 TCP。TCP在传输层同样存在对头阻塞——一旦丢包,整个 TCP连接上的所有数据都要等待重传,所有流都被卡住。
HTTP 3.0 就是为了彻底解决这个问题。
HTTP 3.0 的核心是 QUIC(Quick UDP Internet Connections),一种基于 UDP的传输协议。
UDP 的特点是什么?无连接、不重传、不管顺序——简单粗暴,速度快,但不可靠。
QUIC
在 UDP 之上实现了自己的可靠传输逻辑,把 TCP 的优点移植过来,同时避免了
TCP 的缺点。
HTTP 3.0 的核心改进
1. 彻底抛弃 TCP,全程 UDP
HTTP 3.0 不再使用 TCP,而是直接基于 QUIC。没有 TCP 三次握手,改用 QUIC
自己的连接建立逻辑。
2. 每个流独立,不再互相影响
QUIC 把连接分成多个流(Stream)。丢包了?只影响当前流,其他流照常跑。这就 是真正的无对头阻塞。
3. 0-RTT 快速建立连接
第一次连接需要 1-RTT,之后可以做到 0-RTT——客户端直接发送数据,连接已经建立了。
4. 内置 TLS
HTTP 3.0 把加密直接做进了传输层,而不是像 HTTPS 那样单独跑一个 TLS
层。QUIC 本身就支持加密,而且比 TLS 更快。
一句话总结
HTTP 3.0 = HTTP 2.0 的所有特性 + QUIC(基于 UDP)= 彻底解决对头阻塞 +
更快建立连接 + 内置加密
模块六:总结
一部解决痛点的历史回顾 HTTP 的演进,有一条清晰的脉络:
HTTP 0.9 → HTTP 1.0 → HTTP 1.1 → HTTP 2.0 → HTTP 3.0
每一次升级,都是为了解决上一代暴露出来的核心问题。
-
HTTP 0.9 太简陋,只能发 GET 请求,于是 HTTP 1.0 加入了 POST、HEAD、请求头和响应头。
-
HTTP 1.0 每次请求都要重新建连,效率太低,于是 HTTP 1.1 引入了长连接,多个请求可以复用同一个 TCP 连接。
-
HTTP 1.1 的管道化听起来很美,但响应没有编号,一个请求卡住后面全部排队,实际被浏览器弃用。
-
HTTP 2.0 用二进制分帧和流 ID 彻底解决了这个问题,一个 TCP 连接里可以并发多个请求,互不阻塞。
HTTP 2.0 看起来很完美了,但底层还是 TCP。TCP本身的传输层对头阻塞没有解决,一旦丢包,所有流都受影响。
- HTTP 3.0 直接抛弃TCP,改用基于 UDP 的 QUIC,每个流独立可靠传输,彻底告别了对头阻塞。
各版本一句话定位
- HTTP 0.9:一行 GET,一切的开端
- HTTP 1.0:引入 Header,走向标准化
- HTTP 1.1:长连接为主,但应用层对头阻塞无法根治
- HTTP 2.0:二进制分帧 + 多路复用,从根本上解决对头阻塞
- HTTP 3.0:基于 QUIC(UDP),彻底解决对头阻塞,更快、更安全
面试该怎么答
当面试官问起 HTTP 的演进时,不要只背区别,要讲清为什么需要这些升级。
比如被问到"HTTP 2.0 相比 1.1 有什么改进",可以这样答:
HTTP 1.1 虽然有长连接,但响应没有编号,存在对头阻塞问题。HTTP 2.0
通过二进制分帧和流 ID,把每个请求拆成带编号的帧,在同一个 TCP
连接里并发传输,按流 ID 重组,彻底解决了对头阻塞。
顺着"问题→解决方案→新问题→再解决"的逻辑讲下去