💡前端入门网络协议-HTTP发展

149 阅读5分钟

学习了解一个技术,最好的方法是了解它的来龙去脉,前世今生,对于 HTTP 这项不断打补丁的技术更是如此。下面就从 HTTP 的发展历史来了解下 HTTP 吧

HTTP 的发展历史

诞生背景(1989-1991)

蒂姆·伯纳斯-李在欧洲核子研究中心(CERN)工作时,为了让世界各地的科学家们能够方便地共享文档,发明了:

  • HTML:文档格式
  • HTTP:传输协议
  • URL:资源定位符

这就是万维网(World Wide Web)的雏形。

HTTP/0.9(1991)- 单行协议

最早的 HTTP 协议极其简单:

  • 只支持 GET 方法
  • 只能获取文本内容
  • 完成即断开连接(无状态)

例如:

GET /index.html

<html>
  这是一个简单的 HTML 文件
</html>

HTTP/0.9 - 最简单的请求响应

想象你在餐厅点一杯水:

// 请求
GET /water

// 响应(只能返回文本)
这是一杯水

没有状态码,没有头信息,完全单向沟通。就像你只能说"要水",服务员只能给你水。

HTTP/1.0(1996)- 构建可扩展性

为了支持多种类型的文档,HTTP/1.0 新增了很多重要的特性:

  • 增加了 POST、HEAD 等方法
  • 增加了响应状态码(200、404 等)
  • 引入了 HTTP 头部(Header)
  • 支持多种文档类型(Content-Type)

但仍存在问题:

  1. 每个请求都需要重新建立 TCP 连接
  2. 每个连接只能处理一个请求
  3. 服务器压力大,浏览网站速度慢

例如访问一个网页:

建立连接 -> 请求 HTML -> 断开连接
建立连接 -> 请求 CSS  -> 断开连接
建立连接 -> 请求 JS   -> 断开连接
建立连接 -> 请求图片  -> 断开连接

HTTP/1.0 - 增加了更多信息

现在像正常点餐了:

// 请求
GET /menu.html HTTP/1.0
Host: restaurant.com
Accept: text/html
User-Agent: Mozilla/4.0

// 响应
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 137

<html>
  <head><title>菜单</title></head>

  <body>
    <h1>今日特色</h1>

    <p>红烧肉 - ¥38</p>

  </body>

</html>

可以说明要什么格式,服务器也会告诉你状态(比如:200 成功,404 没找到)。

HTTP/1.1(1997)- 标准化的协议

HTTP/1.1 解决了很多 1.0 的问题:

  1. 长连接(Keep-Alive)
建立连接 -> 请求 HTML
        -> 请求 CSS
        -> 请求 JS
        -> 请求图片
- 一个 TCP 连接可以发送多个请求
- 减少了建立和断开连接的开销

2. 管道机制(Pipeline)

请求:HTML、CSS、JS、图片 ->
响应:<- HTML、<- CSS、<- JS、<- 图片
- 允许在同一个连接中同时发送多个请求
- 但服务器必须按请求顺序返回响应

3. 新增方法 - PUT - DELETE - OPTIONS - TRACE

但仍有一些问题:

  1. 队头阻塞:前面的请求没处理完,后面的请求就要等待
  2. 无法复用连接:每个域名一般最多维护 6 个连接
  3. 头部冗余:每个请求都要携带完整的头部信息

HTTP/1.1 - 可以保持连接

像在餐厅吃饭,不用每次点菜都重新入座:

// 第一个请求
GET /appetizer.html HTTP/1.1
Host: restaurant.com
Connection: keep-alive

// 第一个响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 50

<div>您的开胃菜:沙拉</div>

// 第二个请求(同一个连接)
GET /main-course.html HTTP/1.1
Host: restaurant.com

// 第二个响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 52

<div>您的主菜:牛排</div>

HTTP/2(2015)- 更快的协议

HTTP/2 主要解决了性能问题:

  1. 多路复用(Multiplexing)
请求:HTML ->
     CSS  ->    响应可以乱序返回
     JS   ->    互不影响
     图片 ->
  • 一个连接可以并发处理多个请求和响应
  • 解决了队头阻塞问题
  1. 二进制分帧

    • 将信息分割为更小的帧,提高传输效率
    • 可以乱序发送,根据标识重组
  2. 头部压缩(HPACK)

    • 使用压缩算法减少头部体积
    • 建立头部索引表,重复的头部只发送索引
  3. 服务器推送

    • 服务器可以主动推送资源
    • 比如:请求 HTML 时,服务器直接推送 CSS 和 JS

HTTP/2 - 多路复用

像一个超级服务员,可以同时处理多个需求:

// 并发请求
:method GET
:path /index.html
:scheme https
:authority website.com

:method GET
:path /style.css
:scheme https
:authority website.com

:method GET
:path /script.js
:scheme https
:authority website.com

// 响应可以乱序返回
// 帧1(CSS响应)
:status 200
content-type text/css
{CSS内容}

// 帧2(JS响应)
:status 200
content-type application/javascript
{JS内容}

// 帧3(HTML响应)
:status 200
content-type text/html
{HTML内容}

HTTP/3(2022)- 基于 UDP 的协议

为了解决 TCP 的一些固有问题,HTTP/3 基于 UDP 协议重新设计:

  1. 更快的建立连接
    • TCP 需要三次握手
    • UDP 基于 QUIC 协议,只需要一次握手
  2. 解决了 TCP 队头阻塞
    • TCP 丢包会阻塞整个连接
    • UDP 每个流是独立的,某个流的丢包不会影响其他流

总结:HTTP 的发展历史就是不断解决问题的过程

  • 0.9:解决了文档共享的基本需求
  • 1.0:解决了多种类型文档传输的问题
  • 1.1:解决了连接复用的问题
  • 2.0:解决了性能问题
  • 3.0:解决了传输层的问题

HTTP/3 - 基于 UDP 的全新体验

像是用无人机送餐,更快更灵活:

// QUIC 握手(只需一次)
Client Hello (包含客户端支持的加密套件)
Server Hello (选择加密套件并发送证书)

// 之后可以立即发送数据
:method GET
:path /fast-food.html
:authority quick-restaurant.com

// 即使某个包丢失,其他内容也能正常送达
Stream 1: 汉堡数据
Stream 2: 薯条数据(丢失了一个包,但不影响汉堡的接收)
Stream 3: 可乐数据

有趣的对比:

  • HTTP/0.9 像是简单的路边摊
  • HTTP/1.0 像是正规餐厅
  • HTTP/1.1 像是可以多点几次的自助餐
  • HTTP/2 像是多个服务员同时服务
  • HTTP/3 像是无人机送餐,即使一架出问题其他的还能送

总结

这个文档从历史发展的角度,介绍了每个版本 HTTP 协议要解决的具体问题,并且用简单的例子和图示来说明。这样前端新人可以更容易理解 HTTP 协议的演进过程,以及为什么需要这些改进。

我们平常开发中,使用最多的还是 HTTP/1.1,因为它是目前最广泛使用的版本。

所以下篇文章我们重点学习 HTTP/1.1 的使用,请求和响应的格式。