目录

我们每天打开浏览器、刷短视频、点外卖、扫码支付,背后都在悄悄地发出成千上万个 HTTP 请求。

但你真的了解 HTTP 吗?

HTTP/0.9 凭什么只用一行文本就能传输网页? 为什么 HTTP/1.0 之后还要有 HTTP/1.1,而且一用就是近 20 年? Google 为何要在 UDP 上”另起炉灶”搞出 HTTP/3? 长连接(Keep-Alive)、管线化(Pipelining)、多路复用(Multiplexing)到底解决了什么问题?

今天这篇文章,我们从 1989 年 CERN 的那份提案开始,沿着时间线把 HTTP/0.9 → 1.0 → 1.1 → 2 → 3 这五个版本的诞生背景、发布时间、协议格式、请求方法、连接模型、工作原理与流程,以及它们在不同历史时期的真实应用场景逐一做个介绍。


HTTP 的起源

万维网的诞生 1989 年 3 月,欧洲核子研究组织(CERN)的英国工程师 Tim Berners-Lee(蒂姆·伯纳斯-李) 提交了一份名为《Information Management: A Proposal》的内部提案,目标是解决 CERN 内部海量、分散、格式各异的科研文档之间的”信息孤岛”问题。

他的设想是建立一个超文本(HyperText)系统:用统一资源标识符(URI)定位文档,用超文本传输协议(HTTP)传输文档,用超文本标记语言(HTML)编写文档,三者共同构成后来被称为 World Wide Web(万维网) 的基础。

小知识 , “万维网” ≠ “互联网”

很多人把两者混为一谈。互联网(Internet) 是一套连接全球计算机的物理与网络层基础设施(基于 TCP/IP,1969 年 ARPANET 起步);而 万维网(WWW) 只是运行在互联网之上的一个应用层信息服务。 电子邮件、FTP、即时通讯也都是互联网的应用,但只有 WWW 用的是 HTTP。

HTTP 的"史前时代":0.9 版本

1990 年,Tim Berners-Lee 在 NeXT 计算机上写出了世界上第一个浏览器(同时也是第一个服务器)。 当时并没有正式的协议文档,只有一行简洁的约定,后来被称为 HTTP/0.9。

从"民间协议"到国际标准

HTTP 真正走向标准化,是随着 Web 的爆炸式增长而被迫推动的:

  • 1994 年:HTTP/1.0 草案开始起草,用于解决 0.9 的诸多限制(无头部、无状态码、只能传 HTML)。
  • 1996 年:RFC 1945 以 Informational(信息性文档,非官方标准)状态发布,记录了当时已被广泛实现的 HTTP/1.0。
  • 1997 年:RFC 2068 发布 HTTP/1.1,随后在 1999 年 RFC 2616 中完善,成为统治 Web 近 20 年的事实标准。
  • 2014–2015 年:IETF 的 HTTPbis 工作组 对 2616 进行重构(RFC 7230~7235),并发布 HTTP/2(RFC 7540),首个基于 Google SPDY 的二进制协议。
  • 2022 年:HTTP/3(RFC 9114) 正式标准化,将传输层从 TCP 换成 QUIC(基于 UDP),完成了 HTTP 底层传输的范式转移。

关键转折:2022 年 IETF 还发布了 RFC 9110~9114 系列,将 HTTP 的语义(Semantics, 9110)、缓存(Caching, 9111)、消息语法(Syntax, 9112)与各版本映射彻底解耦,这意味着 HTTP/1.1、HTTP/2、HTTP/3 共享同一套语义定义,区别只在”字节怎么在网络上流动”。

发展脉络

1989  1991      1996       1997/1999   2014~2015   2022
 │     │         │          │           │           │
 ├─提案┤ HTTP/0.9├─HTTP/1.0─┤ HTTP/1.1 ├─ HTTP/2 ──┤ HTTP/3
 │     │         │          │           │           │
 │     │         │          │           │           │
TBL  单行    RFC1945    RFC2068      RFC7540    RFC9114
提案  文本   仅HTML      2616/723x    SPDY衍生   QUIC/UDP
     协议   头部/状态码  长连接/管线化 二进制帧   多路复用

各版本发布时间线

版本发布时间核心 RFC传输层关键里程碑
HTTP/0.91991(非正式)无(仅约定)TCP单行命令、仅 GET、纯 HTML
HTTP/1.01996-05RFC 1945TCP引入请求头/响应头、状态码、多类型内容
HTTP/1.11997-01(RFC 2068)
1999-06(RFC 2616)
RFC 2068 / 2616 / 723xTCP持久连接默认开启、管线化、Host 头
HTTP/22015-05RFC 7540TCP二进制分帧、多路复用、头部压缩 HPACK
HTTP/32022-06RFC 9114QUIC(UDP)彻底解决队头阻塞、0-RTT、连接迁移

⏱ 时间跨度观察:从 0.9 到 1.1 用了约 6 年完成”能用→好用”的跃迁;但从 1.1 到 2 经历了 18 年,从 2 到 3 仅 7 年。 这反映出 Web 性能瓶颈的演进:早期受限于功能缺失,中期受限于协议僵化(中间件兼容性),近期受限于传输层(TCP 队头阻塞)。


各版本简介

下面逐一拆解每个版本的协议格式、请求方法、连接模型、工作原理与流程。

HTTP/0.9 , 协议的"原始形态"

诞生背景:1991 年 Web 还只是 CERN 内部的文档分享工具,需求极其简单,“给我一个 HTML 文件”。

协议格式(其实没有"格式")

客户端请求(仅一行):
  GET /index.html

服务器响应(直接返回文件内容,无头部):
  <HTML>...</HTML>
  (连接立即关闭)

特点:

  • 请求只有 GET 路径 一行,连版本号都没有。
  • 响应只有 HTML 正文,没有任何头部、状态码。
  • 服务器发送完内容后立即关闭 TCP 连接。
  • 不支持图片、CSS、JS,因为无法标识内容类型。

请求方法

方法支持
GET(唯一方法)

工作流

┌────────┐          TCP 三次握手          ┌────────┐
│ Client │ ───────────────────────────▶ │ Server │
└────────┘                              └────────┘
     │                                      │
     │  GET /page.html  (单行,无版本号)     │
     │ ───────────────────────────────────▶ │
     │                                      │
     │  <HTML>...</HTML>  (仅正文,无头)    │
     │ ◀─────────────────────────────────── │
     │                                      │
     │  TCP 连接关闭 (FIN)                   │
     │ ◀──────────────────────────────────▶ │

工作流程:建连 → 发 GET → 收 HTML → 断连。 没错,如你所见,每个资源的获取都要走一遍这个流程。

应用场景

  • CERN 内部文档系统:纯文本/HTML 科研报告浏览。
  • 早期学术 Web(1991–1993):如第一个网站 info.cern.ch(1991 年 8 月上线,截止本文发布时依然可以访问)。
  • 受限于只能传 HTML,很快就无法满足图片、表单等需求。

HTTP/1.0 , 协议的"第一形态"

诞生背景:Web 走出 CERN,商业网站兴起,需要在同一个连接里传输图片、不同格式的文件,并告诉客户端”发生了什么”(成功?找不到?出错?)。

协议格式

请求:
  GET /index.html HTTP/1.0      ← 首次出现版本号
  User-Agent: Mozilla/1.0
  Accept: text/html
  (空行结束头部)

响应:
  HTTP/1.0 200 OK               ← 状态行:版本 + 状态码 + 原因短语
  Content-Type: text/html       ← 内容类型,从此可传图片/CSS/JS
  Content-Length: 1024
  (空行)
  <HTML>...</HTML>

核心新增:

  • 请求头 / 响应头:可携带元信息。
  • 状态码:200/404/500 等,让客户端明确结果。
  • Content-Type:支持 HTML 之外的任意 MIME 类型(图片、视频、JSON…)。
  • Content-Length:让客户端知道响应何时结束。

请求方法(RFC 1945)

方法含义说明
GET获取资源安全且幂等(Safe & Idempotent),参数在 URL
POST提交数据用于表单、上传
HEAD仅取头部用于探测资源是否存在/过期

注:PUT、DELETE 等在 1.1 才规范化,1.0 已有雏形但非强制。

连接模型:默认短连接

HTTP/1.0 默认每个请求/响应对都新建一个 TCP 连接,请求完毕即关闭。 若想复用连接,需显式加 Connection: keep-alive(源自 Netscape 扩展,后于 HTTP/1.1 标准化)。

浏览器加载一个含 3 张图片的页面,HTTP/1.0 默认行为:
  TCP① → GET /page.html → 关闭
  TCP② → GET /a.jpg     → 关闭
  TCP③ → GET /b.jpg     → 关闭
  TCP④ → GET /c.jpg     → 关闭
 (4 次 TCP 握手 + 4 次慢启动,性能极差)

工作流程

Client                                      Server
  │  ── TCP 握手 ──▶                          │
  │  GET /x HTTP/1.0                          │
  │ ─────────────▶                            │
  │  HTTP/1.0 200 OK + 头部 + 正文            │
  │ ◀─────────────                            │
  │  ── TCP 关闭 ──▶                          │

应用场景(1996–1998):

  • 早期商业门户、个人主页、静态资源站。
  • 简单、兼容性最好,但连接开销大,页面资源多时加载极慢。
  • 至今仍常见于简单的状态探测、健康检查接口(因为实现成本最低)。

HTTP/1.1 , 统治 Web 近 20 年的中流砥柱

诞生背景:HTTP/1.0 的短连接模型在”网页越来越重(图片、CSS、JS 暴涨)“时成为性能瓶颈。

1997 年 RFC 2068 发布,1999 年 RFC 2616 完善,核心目标就是复用连接、减少延迟、增强缓存。

协议格式(与 1.0 兼容,头部更丰富)

请求:
  GET /index.html HTTP/1.1
  Host: www.example.com        ← 必填!支持虚拟主机(一台服务器多域名)
  User-Agent: ...
  Accept-Encoding: gzip
  Connection: keep-alive       ← 可选(默认已是持久连接;写 close 才会关闭)
  (空行)

响应:
  HTTP/1.1 200 OK
  Content-Type: text/html; charset=utf-8
  Transfer-Encoding: chunked   ← 支持分块传输(流式)
  Cache-Control: max-age=3600  ← 更强的缓存控制
  (空行)
  <HTML>...</HTML>

请求方法(RFC 2616 规范化)

方法含义幂等说明
GET获取资源安全、幂等
HEAD取头部安全方法(Safe),仅返回头部
POST提交/创建非幂等
PUT替换资源REST 风格更新
DELETE删除资源REST 风格删除
OPTIONS探测支持的方法跨域预检(CORS)
TRACE回显请求诊断用,易引发 XST(Cross-Site Tracing)攻击,现代服务器默认禁用
CONNECT建立隧道—用于 HTTPS 代理

连接模型:持久连接 + 管线化

① 持久连接(Persistent Connection),默认开启

HTTP/1.1 下加载同一页面:
  TCP① → GET /page.html → GET /a.jpg → GET /b.jpg → GET /c.jpg → 关闭
         (一个连接顺序复用,省去 3 次握手/慢启动)

② 管线化(Pipelining),客户端可不等响应就连续发多个请求

Client: GET A → GET B → GET C   (一次性发出)
Server:  resp A → resp B → resp C (按序返回)

现实局限:管线化要求响应严格按请求顺序返回(FIFO),一旦某个响应慢,后面的就被”堵住”,这就是队头阻塞(Head-of-Line Blocking)。加之浏览器/代理兼容性差,管线化实际很少启用。

工作原理与完整流程

Client                                      Server
  │  ── TCP 握手(含 TLS 可选)──▶            │
  │  GET /page HTTP/1.1  (Host 必填)          │
  │ ─────────────▶                            │
  │  HTTP/1.1 200 OK + 头部                   │
  │  Transfer-Encoding: chunked               │
  │ ◀─────────────                            │
  │  数据块1 ─▶ 数据块2 ─▶ ... (流式分块)      │
  │ ◀─────────────                            │
  │  ...持续复用该连接发其他资源...            │
  │  ── 空闲超时 / Connection: close ──▶ 关闭 │

关键机制:

  • Host 头:让一台服务器通过不同域名托管多个站点(虚拟主机)。
  • 分块传输(chunked):服务器无需预先知道 Content-Length,可边生成边发。
  • 强缓存/协商缓存:Cache-Control、ETag、Last-Modified 大幅降低重复请求。
  • 断点续传:Range 头支持范围请求。

历史应用场景(1999 – 2015+)

  • 整个 Web 2.0 时代:博客、电商、社交网络、Web 邮箱。
  • RESTful API:PUT/DELETE/OPTIONS 支撑移动互联网 App 后端。
  • 企业内网、物联网设备管理页:兼容性最佳,几乎无设备不支持。
  • 直至今日仍是默认兜底协议:所有服务器都支持 1.1,是 HTTP/2、3 的协商降级目标。

HTTP/2 , 彻底解决 Web 性能问题

诞生背景:尽管 HTTP/1.1 有持久连接,但一个 TCP 连接同一时刻只能处理一个请求(队头阻塞),浏览器被迫开 6~8 个并行连接来加速,造成资源竞争。

Google 的 SPDY 协议证明了”二进制多路复用”的可行。

2015 年 RFC 7540 基于 SPDY 发布 HTTP/2。

协议格式:从文本到二进制帧

HTTP/2 不再是人类可读的文本行,而是二进制分帧层(Framing Layer):

HTTP/2 数据流(一个 TCP 连接上并发多个流):

  TCP 连接 (单条)
  ┌──────────────────────────────────────────┐
  │  Stream 1: HEADERS + DATA (请求 /page)    │ ↕ 帧交错发送
  │  Stream 3: HEADERS + DATA (请求 /a.jpg)   │ ↕ 互不阻塞
  │  Stream 5: HEADERS + DATA (请求 /b.css)   │ ↕
  └──────────────────────────────────────────┘

  帧结构 (Frame):
  +-----------------------------------------------+
  | Length(24) | Type(8) | Flags(8) | StreamID(31)|
  +-----------------------------------------------+
  |                Frame Payload                  |
  +-----------------------------------------------+

请求方法

与 HTTP/1.1 完全一致(语义不变,仍是 GET/POST/PUT…)。

HTTP/2 改变的只是传输方式,而不是语义。

连接模型:单连接多路复用

  • 多路复用(Multiplexing):一个 TCP 连接上并发多个流(Stream),帧可交错发送、独立到达,彻底消除应用层队头阻塞。
  • 浏览器不再需要开多个连接,默认只建 1 条 TCP 连接。
HTTP/1.1 (6 条连接)          HTTP/2 (1 条连接,多路复用)
  TCP1: A─▶                     Stream1: A ┐
  TCP2: B─▶                     Stream3: B ├─▶ 交错帧 ─▶ 并行响应
  TCP3: C─▶                     Stream5: C ┘
  ... (资源竞争/TCP 拥塞互相影响)

核心新特性

特性说明
多路复用单连接并发多流,消除应用层队头阻塞
头部压缩 HPACK用静态/动态字典压缩冗余头部(1.1 每次都重复发送巨大 Cookie)
服务器推送(Server Push)服务器可主动推送客户端可能需要的资源(如 CSS)
流优先级(Priority)客户端可标识资源重要程度,调度传输顺序
二进制帧解析高效,减少文本协议的开销与歧义

工作流程

Client                                      Server
  │  ── TCP + TLS1.2/1.3 握手 ──▶             │
  │  SETTINGS 帧 (协商参数)                   │
  │ ─────────────▶                            │
  │  HEADERS(Stream1, GET /page)              │
  │  HEADERS(Stream3, GET /style.css)         │  ← 交错发出
  │ ─────────────▶                            │
  │  DATA(Stream1) / DATA(Stream3) 并行返回   │  ← 按流独立
  │ ◀─────────────                            │
  │  (单连接持续承载所有资源)                │

注意:HTTP/2 仍跑在 TCP 上,所以传输层队头阻塞依然存在,若某个 TCP 包丢失,TCP 的有序交付机制要求等待该包重传成功后才能递交给应用层,整条连接的所有流都会被冻结。 这是催生 HTTP/3 的根本原因。

应用场景(2015 – 至今)

  • 高并发 Web 应用:大型电商、新闻门户、SaaS 控制台。
  • 移动端 App API:减少连接数、降低延迟、省电省流量。
  • 主流浏览器默认协商:Chrome、Firefox、Safari 均优先 HTTP/2,且要求 TLS 加密(明文 h2c 极少用)。
  • 据 W3Techs 统计,全球 top 网站中 HTTP/2 已覆盖绝大多数。

HTTP/3 , 基于 QUIC 的彻底重构

诞生背景:HTTP/2 的多路复用被 TCP 层的队头阻塞 卡住了,TCP 保证字节有序,丢一个包就要等重传,整个连接的所有流都被冻结。此外,TCP 建连需 1~3 个 RTT,移动网络切换(Wi-Fi↔4G)会断连重来。

Google 的 QUIC 协议用 UDP 重新实现可靠传输,2022 年 RFC 9114 将其定为 HTTP/3。

协议格式:QUIC 上的 HTTP 语义

HTTP/3 分层:
  应用层: HTTP 语义 (与 1.1/2 相同: 方法/状态码/头部)
     ↓ 映射为 HTTP/3 帧
  表示层: QPACK (头部压缩,HPACK 的 QUIC 适配版)
     ↓
  传输层: QUIC (运行在 UDP 之上)
     ├─ 可靠、有序的 Stream
     ├─ 内置 TLS 1.3
     └─ 独立丢包重传,互不影响

  QUIC 数据包 (UDP 载荷):
  +-------------------------------------------+
  | Header (Connection ID, Packet Number)     |
  +-------------------------------------------+
  | STREAM 帧 (Stream A 数据,独立)           |
  | STREAM 帧 (Stream B 数据,独立)           |  ← 任一丢失只影响自身流
  +-------------------------------------------+

请求方法

同样复用 HTTP 语义,方法集合不变。

连接模型:UDP + QUIC 流

  • 每个 QUIC 连接由 Connection ID 标识,而非(IP, 端口)四元组。
  • 连接内同样有多路流(Stream),但流之间完全独立,Stream A 丢包,只重传 A,B/C 照常传输(真正消除队头阻塞)。
  • 0-RTT / 1-RTT 建连:结合 TLS 1.3,可缓存会话,后续访问零往返发数据。
HTTP/2 over TCP (丢包影响所有流):
  TCP包丢失 ─▶ 整条连接冻结等待重传 ─▶ 所有 Stream 卡住

HTTP/3 over QUIC (丢包仅影响单流):
  QUIC Stream A 丢包 ─▶ 仅 A 重传,B/C 继续 ─▶ 无全局阻塞

核心新特性

特性说明
QUIC 传输层基于 UDP,内置可靠、拥塞控制、加密
彻底无队头阻塞流级独立丢包恢复
连接迁移切换网络(IP 变)靠 Connection ID 不断连
0-RTT 握手复用上下文,首包即可带数据
QPACK 头部压缩解决 HPACK 在 QUIC 上的队头依赖

工作流程

Client                                      Server
  │  ── UDP 单 RTT (含 TLS1.3) 握手 ──▶       │
  │  QUIC INITIAL + HTTP/3 SETTINGS          │
  │ ─────────────▶                            │
  │  STREAM(0, GET /page)  并行              │
  │  STREAM(4, GET /img)   并行              │
  │ ─────────────▶                            │
  │  STREAM 响应 独立到达 (可乱序)            │
  │ ◀─────────────                            │
  │  切 Wi-Fi→4G: Connection ID 不变,连接保活 │

应用场景(2022 – 至今,快速增长)

  • 弱网/移动场景:视频、直播、短视频(抖音、YouTube)受益于 0-RTT 与抗丢包。
  • 高延迟卫星/跨国链路:减少建连往返,连接迁移友好。
  • 大型内容分发(CDN):Cloudflare、Google、Meta 等大规模部署。
  • 对延迟极度敏感的交互:实时游戏、WebRTC 信令、金融行情推送。

据多家 CDN 公开数据,HTTP/3 在全球流量中的占比已快速攀升,成为高流量站点的标配选项(通常 1.1 / 2 / 3 同时支持,按客户端能力协商)。


版本特性横向对比

核心能力总表

维度HTTP/0.9HTTP/1.0HTTP/1.1HTTP/2HTTP/3
发布年份199119961997/199920152022
传输层TCPTCPTCPTCPQUIC/UDP
协议格式纯文本文本文本二进制帧二进制帧(QUIC)
默认连接短连接短连接持久连接单连接多路复用单连接多路复用
多路复用(管线化受限)
队头阻塞连接级连接级连接+应用级仅 TCP 级无
头部压缩HPACKQPACK
请求方法GETGET/POST/HEAD+PUT/DELETE/…同 1.1同 1.1
状态码
服务器推送(Chrome/Firefox 已禁用)(协议支持 EXTENDED_PUSH, 但主流浏览器均未启用)
加密无可选(HTTPS)可选实际需 TLS内置 TLS1.3

连接模型演进图示

0.9/1.0:  请求①[TCP]→ 断 → 请求②[TCP]→ 断 → 请求③[TCP]→ 断   (串行、浪费)
1.1:      请求①②③④ 在同一 [TCP] 上顺序复用                 (省握手,仍串行响应)
2:        单 [TCP] 上 Stream1/3/5 帧交错并行                 (应用层并行,受 TCP 阻塞)
3:        单 [UDP/QUIC] 上 Stream 独立丢包恢复 + 连接迁移     (彻底并行)

各时期的典型应用场景

时期主流版本典型应用选择理由
1991–19950.9CERN 文档、首个网站需求极简,仅传 HTML
1996–19981.0早期门户、个人站引入头部/类型,兼容简单
1999–20141.1Web 2.0、REST API、电商持久连接+缓存,稳定通用
2015–20211.1 + 2大型 SaaS、移动 App2 提性能,1.1 兜底降级
2022–至今1.1 + 2 + 3短视频、CDN、跨国服务3 抗弱网/低延迟,1.1/2 兼容

总结

HTTP 的三十余年演进,本质是在”功能 → 性能 → 传输可靠性”三条主线上不断逼近极限:

  1. 0.9 → 1.0:补全了”像样的协议”该有的头部、状态码、类型标识。
  2. 1.0 → 1.1:用持久连接、缓存、Host 头,把”能跑”变成”好用”,统治 Web 近 20 年。
  3. 1.1 → 2:用二进制分帧与多路复用,在不换传输层的前提下榨干 TCP 性能。
  4. 2 → 3:直面 TCP 的固有缺陷,迁到 QUIC/UDP,彻底消灭队头阻塞并支持连接迁移。

实际工程中如何选?

  • 面向公网 Web / API:优先 HTTP/2(兼容性、性能最佳),并同时开启 HTTP/1.1 作为降级。
  • 弱网、移动端、跨国高延迟:积极启用 HTTP/3,体验提升明显。
  • 内网/老旧设备/健康检查:HTTP/1.1 足矣,简单可靠。
  • 三者并非互斥:现代服务器(Nginx、Caddy、Envoy)通常 1.1 / 2 / 3 同时监听,由客户端 ALPN 协商决定,这正是 HTTP 语义与传输解耦(RFC 9110+)带来的最大红利。

最后的思考:HTTP 的下一步会是什么?随着 HTTP/3 扩展(如 WebTransport)、MASQUE 代理、以及 QUIC 在更多场景下沉,应用层协议正从”请求-响应”走向”双向实时流”。但无论字节如何流动,那套 1989 年定下的 URI + 方法 + 状态码 语义,仍将是 Web 不变的根基。

从HTTP的发展过程,也能说明一个道理,没有任何一个方案是完美的,只有在不断的迭代中,才能找到最适合的方案,那些一开始就追求完美的我一直认为他是傻缺。