1. 基础背景
- OSI 七层模型:HTTP 位于 应用层,依赖 传输层 (TCP/UDP) 。
- TCP/IP:早期 HTTP 基于 TCP,TCP 是可靠的面向连接协议(需三次握手、四次挥手)。
- HTTP 本质:一种 请求-响应模式 的应用层协议。
- 目标:让浏览器尽可能快、稳定地获取资源(HTML、CSS、JS、图片等)。
理解 HTTP,必须先理解它在网络中的位置。
| OSI 七层模型 | 功能简述 | 对应 TCP/IP 模型 |
|---|---|---|
| 7. 应用层(Application) | 用户接口,直接为应用提供服务(如浏览器) | 应用层 |
| 6. 表示层(Presentation) | 数据格式转换、加密解密 | (合并到应用层) |
| 5. 会话层(Session) | 建立、管理、终止会话 | (合并到应用层) |
| 4. 传输层(Transport) | 提供端到端通信(TCP / UDP) | 传输层 |
| 3. 网络层(Network) | 路由选择、IP 寻址(IP 协议) | 网络层 |
| 2. 数据链路层(Data Link) | 物理寻址(MAC 地址)、帧传输 | 数据链路层 |
| 1. 物理层(Physical) | 比特流传输(电缆、光纤等) | 物理层 |
HTTP 属于应用层协议,它依赖下层(传输层 TCP/UDP、网络层 IP)完成数据传输。
2. HTTP 版本演进
🔹 HTTP 0.9(1991 年)
-
特点:
- 只支持 GET 请求。
- 响应内容是 纯文本 HTML,无请求头/响应头。
- 不能传图片、CSS、JS 等资源。
- 无状态,每次请求都是独立的,每一个连接都是一个新的连接。
-
限制:仅能显示极简网页。
🔹 HTTP 1.0(1996 年)
-
新特性:
- 引入 请求头/响应头,支持多种数据类型(MIME type,如图片、CSS、JS)。
- 支持 Cookie(用于状态保持),但协议本身仍是 无状态。
-
问题:
- 短连接:每次请求都要重新建立 TCP 连接(握手 + 断开),开销大。
- 对同一域名下多个资源,需多次 TCP 建立/关闭。
🔹 HTTP 1.1(1997 年,至今仍广泛使用)
-
关键改进:
- 长连接(Keep-Alive) :一个 TCP 连接可复用,减少频繁建立连接的开销。
- 管道化(Pipelining) :允许一个连接中同时发送多个请求,但 响应必须按顺序返回 → 产生 (响应)队头阻塞 (Head-of-line blocking) 。
- 分块传输(Chunked Transfer Encoding) :服务器可以一边生成一边发送数据,提升大文件/动态数据传输效率。
-
问题:
- 存在 队头阻塞,如果前一个响应很慢,后续响应必须等待。
- 浏览器并发限制(同一域名下通常 6 个并发 TCP)。
队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。
如果页面有 20 个资源(图片、JS、CSS),前 6 个可以并行下载,后面的必须排队等待。
尝试解决:
- 域名分片。由于同一域名下通常只能允许同时建立 6 个 TCP持久连接,将同一页面的资源分散到不同域名下,提升连接上限。
缺点:这会导致资源加载变成“串行+并行”的混合模式,整体加载时间变长。
2. 合并小文件。每个 HTTP 请求都有开销(TCP 握手、HTTP 头部、网络延迟)。 加载 100 个 1KB 的小图标,远比加载 1 个 100KB 的文件慢得多(因为有 100 次请求开销)。可以使用精灵图,
Spriting合并多张小图为一张大图,然后用js或css将大图重新切割。
缺点:
- 如果一个图标修改了,整个大图或 JS 文件都需要重新下载。
- 首屏加载变慢:即使只用到其中一小部分,也要下载整个大文件。
- 维护困难:精灵图需要手动维护坐标。
- 使用内联。将小图片转换为 Base64 编码,直接嵌入 CSS 或 HTML 中,减少网络请求次数。
.icon {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...);
}
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...">
缺点:
- Base64 编码后体积比原文件大 33% 左右
- 无法被浏览器单独缓存:每次 CSS/HTML 更新,图片也要重新下载
- 增加 CSS/HTML 文件体积,可能阻塞渲染
- 合并 JS 文件,减少请求数量。拼接将多个体积较小的
JavaScript使用webpack,vite等工具打包成1个体积更大的JavaScript文件。
缺点:
- 如果其中1个文件的改动就会导致大量数据被重新下载多个文件。
- 首屏加载慢:用户可能只用到其中 10% 的代码,却要下载 100%。
🔹 HTTP 2(2015 年,主流新标准)
- 核心特性:
- 多路复用(Multiplexing) :一个 TCP 连接内并发多个请求和响应,解决了 HTTP/1.1 的(响应)队头阻塞。(HTTP 1.1 管道化使得一个TCP连接请求可以并行请求,但响应必须按顺序返回,产生队头堵塞)
- 二进制帧:将请求和响应数据拆分成带有 ID 的二进制帧,交错传输,客户端根据 ID 重组。
- 头部压缩(HPACK) :减少重复 Header 的传输(如 Cookie)。
- 服务器推送(Server Push) :服务端可主动推送资源(如 HTML 页面加载时,提前推送 CSS/JS)。
同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。
优点:
同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,这样整个页面资源的下载过程只需要一次慢启动。
并行交错地发送多个请求/响应,请求/响应之间互不影响。
- 问题:
- 未彻底解决队头阻塞:底层依旧基于 TCP → 如果 TCP 丢包,整个连接都会阻塞(TCP 层面的队头阻塞仍存在)。
- 多路复用容易超时:大批量的请求同时发送,由于 HTTP2 连接内存在多个并行的流,而网络带宽和服务器资源有限,每个流的资源会被稀释,虽然它们开始时间相差更短,但却都可能超时。
🔹 HTTP 3(2018 年后,逐渐普及)
- 最大革新:基于 QUIC 协议(UDP 之上实现可靠传输) 。
- UDP 本身是“无连接、不可靠”的:不保证送达、不保证顺序、不重传。
- QUIC 在 UDP 之上构建了可靠传输机制:
- 数据包重传:丢失的 QUIC 数据包会重传。
- 拥塞控制:动态调整发送速率,避免网络拥塞。
- 在“流(Stream)”级别保证数据顺序:QUIC 连接内可以创建多个独立的流(Stream) ,每个流传输一个资源(如 JS、CSS、图片)。
- 流量控制:防止接收方被淹没。
📌 本质:QUIC 用应用层代码实现了 TCP 的可靠性,但摆脱了 TCP 的内核限制,更灵活。
- 优点:
- 减少握手延迟:TLS 1.3 + QUIC,可实现 0-RTT 连接恢复。
- 彻底解决 TCP 层队头阻塞:QUIC 在应用层做多路复用,即使丢包也只影响单个流,不影响整个连接。
- 更适合弱网环境(移动端切换 WiFi/4G,连接恢复更快)。
- 现状:Chrome、YouTube、Google 已广泛应用,CDN 和大厂在推动普及。
3. HTTP1.1 管道化和 HTTP2 多路复用
管道化—— HTTP/1.1 的“伪并行”
管道化允许客户端在同一个持久连接上,不等待前一个响应返回,就发送多个连续的请求。
客户端 服务器
| |
|--- 请求1 (GET /a.html) ------>| ← 客户端发送请求1
|--- 请求2 (GET /b.css) ------>| ← 客户端**立即**发送请求2(无需等响应1)
|--- 请求3 (GET /c.js) ------>| ← 客户端**立即**发送请求3
|<-- 响应1 (200 OK, a.html) ----| ← 服务器必须按顺序返回响应1
|<-- 响应2 (200 OK, b.css) ----| ← 必须等响应1发完,才能发响应2
|<-- 响应3 (200 OK, c.js) ----| ← 必须等响应2发完,才能发响应3
- 请求可以“管道式”连续发送(客户端视角是“并行”的)。
- 响应必须严格按请求顺序返回(FIFO,先进先出)。
- 底层仍是 TCP 字节流,所有请求和响应在同一个“管道”里串行传输。
多路复用—— HTTP/2 的“真并行”
多路复用通过二进制分帧层,允许在同一个 TCP 连接上,并行交错地发送和接收多个请求和响应,互不阻塞。
HTTP/2 将所有 HTTP 消息(请求、响应)分解为小的二进制帧(Frame),每个帧带有:
- Stream ID:标识属于哪个请求/响应流。
- 帧类型:如
HEADERS(头部帧)、DATA(数据帧)。
客户端 服务器
| |
|--- [Stream1: HEADERS] ------->| ← 发送请求1的头部
|--- [Stream2: HEADERS] ------->| ← 发送请求2的头部
|--- [Stream1: DATA] ------->| ← 发送请求1的数据(如有)
|<-- [Stream2: HEADERS] -------| ← 返回响应2的头部(**先准备好就先发**)
|<-- [Stream2: DATA] -------| ← 返回响应2的数据
|<-- [Stream1: HEADERS] -------| ← 返回响应1的头部(后准备好)
|<-- [Stream1: DATA] -------| ← 返回响应1的数据
- 请求和响应的帧可以交错传输。
- 每个流(Stream)独立,响应可以乱序返回。
- 谁先准备好,谁就先发,不互相阻塞。
- 底层是二进制分帧,不再是文本+字节流。
缺点:还是基于TCP连接,如果TCP存在丢包,整个连接会阻塞。
4. HTTP 与 HTTPS
- HTTP:明文传输,安全性差。
- HTTPS:HTTP + TLS/SSL 加密,确保 数据机密性、完整性、身份认证。
- HTTPS 建立在 TCP(三次握手)+ TLS(握手协商) 之上。
5. TCP vs UDP
- TCP:面向连接、可靠传输(有序、无丢失),适合 HTTP、文件传输。
- UDP:无连接、不保证可靠性,但延迟低,适合视频直播、游戏、HTTP/3(QUIC)。
6. HTTP 各版本对比表
| 版本 | 时间 | 主要特性 | 问题/不足 |
|---|---|---|---|
| 0.9 | 1991 | 只支持 GET ,响应仅 HTML,无 header | 只能传文本,不能传图片/JS/CSS |
| 1.0 | 1996 | 引入 请求头/响应头 ,支持多种资源类型,Cookie | 短连接,每次请求都要新建 TCP |
| 1.1 | 1997 | 长连接 (Keep-Alive) ,管道化 (pipelining) ,分块传输 | 仍有 队头阻塞,并发有限 (6 个/域名) |
| 2.0 | 2015 | 多路复用 (一个 TCP 并发多请求) ,二进制帧 ,头部压缩 ,服务器推送 | 依赖 TCP,丢包时整个连接阻塞 |
| 3.0 | 2018+ | 基于 QUIC(UDP) ,0-RTT 建连 ,弱网优化 ,彻底解决队头阻塞 | 普及中,旧设备/服务器支持不足 |