文章目录
  1. 1. HTTP/0.9
  2. 2. HTTP/1.0
  3. 3. HTTP/1.1
  4. 4. HTTP/2
  5. 5. 总结
  6. 6. 顺便提一句
  7. 7. 参考链接

HTTP 协议作为应用层重要的网络协议,同时也随着时代的发展不断演进。从最初的 HTTP/0.9 到 HTTP/1.0 再到 HTTP/1.1 以至于到现在的最新版本 HTTP/2 。 每个版本的演进都是为了解决网络传输协议中的痛点,下面就来总结下每个版本到底都更新了些什么。

HTTP/0.9

HTTP 的 1991原型版本,这个原型版本定义的初衷是为了传输简单的HTML对象,因此在设计上有很多严重的缺陷,例如:

  1. 只支持GET方法
  2. 不支持多媒体内容的MIME类型
  3. 不支持 HTTP HEADER

正是因为这些硬伤,所以这个版本存活没多久就被新的版本取代了。

HTTP/1.0

既然是新的版本,那么上一版本的这些硬伤就应该被妥善解决。
因此 1.0 版本新增:

  1. 支持多媒体格式文件(图片、视频等)的传输
  2. 支持更多除了GET之外的HTTP方法(POST)
  3. 添加状态码(例如: 200 OK,301 move permanently , 404 not found,500 internal server error 详细内容参见这里
  4. 多字符集,multi-part type, 版本号 等功能支持
  5. HTTP HEADER

那么这个版本又有什么问题呢?

  1. 每个TCP连接只能发送一个请求,数据发送完毕后连接就关闭了,如果要请求其他资源就需要重新建立连接。换句话说就是不支持后来的持久连接 keep-live 功能 。
  2. 不支持虚拟主机和代理连接功能。

HTTP/1.1

同样上个版本的硬伤,下个版本都需要妥善地解决。
因此,1.1版本新增:

  1. 持久连接(persistent connection),并且规定对于同一个域名(这里同一根域名下的子域名属于不同域名)允许同时建立6个连接。
  2. 管道机制 (pipelining)
    在没有管道机制之前,假设完成一个操作需要一系列的请求(例如[A,B,C,D])需要A发送请求并完成数据传输后,B才能发送请求,依次类推。
    引入了pipelining机制后,允许B可以在A没有收到数据的情况下发送请求,但是服务端还是会按照A,B的顺序响应,先处理完A的请求后再处理B的请求。
  3. 由于一个持久连接会有多个回应,就有必要区分数据包是属于哪个回应的,对应的就有 content-length , Transfer-Encoding等机制来保证。
  4. 增加更多HTTP方法(PUT,PATCH,DELETE,HEAD,OPTIONS)

那么这样一个改进的版本会有什么问题呢?
主要还是持久连接上的问题,你会问:持久连接解决了频繁创建连接的高代价问题,管道机制解决了请求必须顺序发送的时序问题,似乎主要问题得到了解决,但是,注意但是来了,这些做法只是从连接的发送方来解决,服务方依然是按照顺序依次处理请求。这就会有排队现象,这个处理慢的请求会拖慢整个网站速度,尤其是这个慢的请求越靠前影响越大。所以说现有流行的http版本的问题会是“排队等待阻塞问题”

那这个问题在新版本出现之前是怎样解决的呢?

  • 比如压缩css、js文件,减小网络传输数据量。
  • 合并小文件,减少请求数量。
  • 域名分片(domain sharding)

这里单独拿出域名分片来说一说:
上面不是说到每个持久连接下不是有6个域名同时建立连接的限制么?
我们聪明的工程师想到,好像我们可以用这6个域名搞事情。比如说有这样一个例子: 现在有个网页上面会有3个比较大的图片文件,如果这三个文件放在同一个持久连接下,那么这三个文件会依次获得从服务器的响应。如果我们将这三个图片放在不同的域名下然后分别创建持久连接,那么这里就解决了请求排队等待的问题。
上面的这种做法你会发现在很多主流的网站都有使用,后来这也成为大流量、对网站响应速度有高要求的站点的网站优化常用手段。
注意到什么问题么?似乎这个解决方案解决了排队等待阻塞的问题,但是它是用创建新的持久连接为代价来做的,这种方案适用的场景还是属于创建连接代价小于排队代价的场景。这种优化其实也是一种trade off。
说到底,这个排队等待阻塞的问题在HTTP/1.1版本内还是一个痛点。那我们就只有寄希望于后续版本从根本上解决这个问题。

HTTP/2

HTTP/2 是2015正式发布。
HTTP/2最激动人心的部分莫过于使用了

  • 多路复用的通信方式
    这一通信方式的改变,从根本上解决了“排队等待阻塞”的问题。
    说的这么好,那么多路复用到底是怎样工作的呢?
    举个例子,一个连接上会有A,B两个请求,如果未使用多路复用的通信方式的时候,那么A,B可以依次发送请求,由于服务端是按照顺序依次处理请求的,所以B一定是等到服务端返回A的数据之后才接收到数据。这样是不是很低效?
    那么使用了多路复用后又是怎样的情况呢?
    A,B发送完请求后,服务端会首先将已经处理好的请求返回,而并不是必须等待A完成后再发送B,这样其实是打乱了返回数据包顺序的限制,从而使队列不再等待。
  • 数据流
    由于上面的数据包返回不再按照请求的顺序返回,因此需要使用一种机制来标记数据包属于哪个请求,在这样的需求下就诞生了“流”的概念。
    一个请求的的所有数据包被称为流,每个流都有一个唯一的ID编号,这样就区分出了数据包属于哪个流。
    同时HTTP/2 还规定可以在不关闭连接的情况下取消数据的传输,这个在之前的版本是想都不敢想的。
    既然顺序已经放开,那么可以要求重要的流数据优先传输么?当然可以,HTTP/2 支持流优先级的设定。

  • 二进制协议
    HTTP/2之前 HTTP HEADER 部分都是以文本的形式传输,而BODY部分可以选择使用文本或者二进制的方式传输。
    而到了HTTP/2 HEADER和BODY部分都需要使用二进制传输,并且统称这些为帧,一是减小网络传输数据量,另一个是为了之后协议的扩展打基础。

  • HEADER 信息压缩
    由于HTTP是不带有状态的,每次请求必须附上所有信息。这样就造成HEADER的一部分信息重复。
    HTTP/2在HEADER部分引入 header compression 机制。使得HEADER信息传输更有效率。

  • 服务推送 (server push)
    HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。

总结

我们纵观HTTP协议的发展历史,从原型版本的HTTP/0.9 到功能基本完整的 HTTP/1.0 再到通信方式改进的 HTTP/1.1 再到性能大幅提升的 HTTP/2.0 这俨然是一个软件迭代发展的路径。
原型阶段的协议只是为了支持简单的html文本信息传输。
到了1.0版本可以支持多媒体文件的传输、状态码、HEADER以及更多HTTP方法使得这个正式的版本能够满足多媒体的互联网传输需求。
再到1.1版本大家发现随着文件越来越大,传输速度成为制约互联网发展的瓶颈,于是便有了持久连接和管道机制的解决方案。
不断变化的环境促使人们不断追寻更高效的传输方式,于是便有了多路复用的HTTP/2。
相信在不久的将来还会有更高效的HTTP版本的协议出现。

顺便提一句

是不是HTTP/2 就是最高效的呢?
答案显然是否定的,注意到HTTP协议其实是应用层的协议,以上的演进也都是在这个层面展开的,那么在它下一层传输层的协议是否有提升空间呢?
是的于是就有了基于UDP协议封装的一个高效可靠传输协议QUIC

参考链接

阮一峰博客
孙宁GDGFest分享

文章目录
  1. 1. HTTP/0.9
  2. 2. HTTP/1.0
  3. 3. HTTP/1.1
  4. 4. HTTP/2
  5. 5. 总结
  6. 6. 顺便提一句
  7. 7. 参考链接