前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >HTTP 演进史

HTTP 演进史

作者头像
菜皮日记
发布2023-12-18 14:34:05
1540
发布2023-12-18 14:34:05
举报
文章被收录于专栏:菜皮日记菜皮日记

HTTP 的发展要追溯到万维网的发明,1989 年,当时在 CERN 工作的 Tim Berners-Lee 博士写了一份关于建立一个通过网络传输超文本系统的报告。这个系统起初被命名为 Mesh,在随后的 1990 年项目实施期间被更名为万维网(World Wide Web)。

万维网在现有的 TCP 和 IP 协议基础之上建立,由四个部分组成:

  • 一个用来表示超文本文档的文本格式,超文本标记语言(HTML)。
  • 一个用来交换超文本文档的简单协议,超文本传输协议(HTTP)。
  • 一个显示(以及编辑)超文本文档的客户端,即网络浏览器。第一个网络浏览器被称为 WorldWideWeb
  • 一个服务器用于提供可访问的文档,即 httpd 的前身。
HTTP/0.9 1991年

最初的 HTTP 协议并没有版本号,0.9 实际上是为了跟后续的 1.0 版本作区分。总的来说 0.9 版本十分简陋,功能单一。

特点:

  • 只支持 GET 请求,在其后面跟上目标资源的路径
  • 没有 HTTP 头部

不足:

  • 因为没有 HTTP 头部,所以除了文本类型无法区分和传输其他类型
  • 没有状态码和错误码,一旦出现问题,只能返回一个固定的错误页面

一个典型的请求:

代码语言:javascript
复制

GET /mypage.html

一个典型的响应:

代码语言:javascript
复制

<html>
  这是一个非常简单的 HTML 页面
</html>
HTTP/1.0 1996年

在 0.9 基础上做了扩展,支持传输更多类型的内容。

特点:

  • 在请求中明确了版本号
  • 增加响应状态码
  • 增加 HTTP 头,使传输资源更加灵活,如:
    • Content-type:通过指定不同的 MIME type,表明资源的格式,如 text/html、text/css、image/png、application/javascript、application/octet-stream 等
    • Accept-Encoding / Content-Encoding:表明客户端支持的压缩类型和响应中使用的压缩类型

不足:

  • 每个 TCP 连接只能发送一个请求,造成了连接效率低下。后续在请求和响应头中增加了一个非标准的 Connection: keep-alive,告知双方请求可以复用同一条 TCP 连接而不是每次请求响应后都关闭连接。不过由于不是标准字段,不同实现的行为可能不一致,因此没有从根本上解决。

一个典型的文本类型的请求和响应

代码语言:javascript
复制

GET /mypage.html HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:31 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/html
<HTML>
一个包含图片的页面
  <IMG SRC="/myimage.gif">
</HTML>

典型的图片类型的请求和响应

代码语言:javascript
复制

GET /myimage.gif HTTP/1.0
User-Agent: NCSA_Mosaic/2.0 (Windows 3.1)

200 OK
Date: Tue, 15 Nov 1994 08:12:32 GMT
Server: CERN/3.0 libwww/2.17
Content-Type: text/gif
(这里是图片内容)
HTTP/1.1 1997年

HTTP/1.1 消除了大量歧义内容并引入了多项改进

特点:

  • 持久连接复用成为默认,不需要声明 Connection: keep-alive,想要关闭可以在响应中增加 Connection: close 声明
  • pipelining 管道,可以一次性发送多个请求,避免了此前一次只能发送一个请求的情况,不过响应需要按照发送的顺序来回复。
  • 增加几种 HTTP 方法
  • 增加分块传输的流模式,响应头携带 Transfer-Encoding:chunked 并在每一个分块增加 Content-Length 表明当前块长度,并在所有内容传输完成的最后追加一个 Content-Length:0 表明传输完成。
  • 增加 range 、Content-Range 相关头,用来支持续传和分段请求。

不足:

  • 存在 Head of line blocking 队头阻塞问题,即同一个连接中有一个请求阻塞了,后续所有请求都将被阻塞。

通过同一个连接实现的请求响应:

代码语言:javascript
复制

GET /zh-CN/docs/Glossary/Simple_header HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/zh-CN/docs/Glossary/Simple_header

200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Jul 2016 10:55:30 GMT
Etag: "547fa7e369ef56031dd3bff2ace9fc0832eb251a"
Keep-Alive: timeout=5, max=1000
Last-Modified: Tue, 19 Jul 2016 00:59:33 GMT
Server: Apache
Transfer-Encoding: chunked
Vary: Cookie, Accept-Encoding

(content)


GET /static/img/header-background.png HTTP/1.1
Host: developer.mozilla.org
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://developer.mozilla.org/zh-CN/docs/Glossary/Simple_header

200 OK
Age: 9578461
Cache-Control: public, max-age=315360000
Connection: keep-alive
Content-Length: 3077
Content-Type: image/png
Date: Thu, 31 Mar 2016 13:34:46 GMT
Last-Modified: Wed, 21 Oct 2015 18:27:50 GMT
Server: Apache

(image content of 3077 bytes)
HTTP/2 2015年

说到 HTTP/2 就不得不提 SPDY,SPDY 是 Google 开发的一个开放网络协议,旨在通过减少延迟来加快网页加载速度。SPDY 在许多方面是 HTTP/2 的先驱,并直接影响了 HTTP/2 的设计和实现。

特点:

  • 兼容 HTTP/1.1
  • 全部使用二进制传输,传输效率更高
  • 引入了多路复用技术,结合 stream 流和 frame 帧的概念,解决了队头阻塞问题。
    • HTTP/1.1 并发请求数量针对每个域名都有限制,而 HTTP/2 可以使用一个连接发送不同业务请求,每个请求通过 streamID 区分,每个 stream 中可以传输多个 message,每个 message 由多个 frame 组成,frame 就是传输的最小单位。
    • 发送时不同请求通过同一个连接并发发送,服务端接到后处理一个就可以返回一个,响应时根据唯一的 streamID 组装响应内容即可。如此避免了 HTTP/1.1 的队头阻塞问题。
  • 支持首部压缩,在同一个连接的不同请求中大部分 header 都是重复的,HTTP/2 使用 HPACK 算法对 header 进行压缩。压缩涉及到很多细节方法
    • 静态表将常见的首部字段都编了号,发送这些首部时,其 key 名直接发送对应的编号即可。
    • 动态表一开始是空的,将随着请求过程中出现的一些不在静态表中的首部填充进去,获得新的编号。
    • 不论静态表还是动态表,其 value 如果是变化的,则使用哈夫曼编码压缩。
  • 支持服务器推送,请求一个网页的同时,还可能需要网页中依赖的静态资源,此时服务端就可以推送这些资源,无须等待客户端主动请求。

不足:

  • HTTP/2 作为应用层协议实际上已经比较完美了,但由于基于 TCP,所以避免不了受 TCP 的特性所影响导致的性能瓶颈,例如三次握手和四次挥手,慢启动和拥塞控制等等,严格来说这些不能算是问题,是设计理念不同的必然结果。
  • 要求 TLS 加密,也增加了建立连接的耗时
  • 移动设备可能频繁切换信号源,导致 socket 四元组发生变化,连接被迫失效,需要重连。

首部压缩的例子:

静态表包括了一些常用的首部字段名称和值。例如:

  • 索引 1::authority
  • 索引 2::method: GET
  • ...
  • 索引 40:content-type: application/json

动态表最初是空的,但会随着连接的使用而填充。假设我们有一个请求,其中包括一个不常见的首部字段:

  • custom-header: example-value

这个字段可以添加到动态表中,并分配一个索引,例如索引 41。

我们可以使用静态表和动态表中的索引来表示这些字段:

  • :method: GET 在静态表中,索引为 2
  • :authority: www.example.com 可以使用索引 1 和哈夫曼编码来压缩 www.example.com
  • custom-header: example-value 在动态表中,索引为 41

最终的首部压缩结果:

  • 索引 2
  • 索引 1 + 哈夫曼编码的 www.example.com
  • 索引 41 + 哈夫曼编码的 www.example.com
HTTP/3 2018年提案 2020年正式

HTTP/3 是基于 QUIC 协议的 HTTP 版本,致力于进一步提高性能。

特点:

  • 在 UDP 基础上构建,满足可靠数据传输的同时,相较 TCP 有很大性能提升。
  • 基于 TLS 1.3 快速建立安全连接
  • 连接迁移,不使用 TCP 四元组而是使用一个 64位 ID来标识连接,当发生网络环境的变化时,可以不需要重新建立连接。

不过 HTTP/3 的改动相对来说是最大的,目前看推广的覆盖率并没有之前的速度快。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HTTP/0.9 1991年
  • HTTP/1.0 1996年
  • HTTP/1.1 1997年
  • HTTP/2 2015年
  • HTTP/3 2018年提案 2020年正式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档