一、HTTP/1.0
1996年5月,HTTP/1.0版本发布,为了提高系统的效率,HTTP/1.0规定浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接,服务器完成请求处理后立即断开TCP连接,服务器不跟踪海个客户也不记录过去的请求。
请注意上面提到的HTTP/1.0中浏览器与服务器只保持短暂的连接,连接无法复用。也就是说每个TCP连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
我们知道TCP连接的建立需要三次握手,是很耗费时间的一个过程。所以,HTTP/1.O版本的性能比较差。现在,随便打开一个网页,上面都会有很多图片、视频等资源,HTTP/1.0显然无法满足性能要求。
二、HTTP/1.1
1、持久连接
HTTP/1.0 中一个 TCP 连接只能发送一个请求和响应,而 HTTP/1.1 进行了优化,同一个 TCP 连接可以发送多次 HTTP 请求,减少了建立和关闭连接的性能开销。
2、管道机制
持久连接虽然可以多个请求复用同一个连接,但是每次都需要等到上一个请求响应完成后,才能发送下一个请求。管道机制中,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,即相当于同时发出多个请求,因而可以减少整体的响应时间。
问题:采用管道机制虽然可以发送多个请求,但是服务器必须按照接收请求的顺序依次发送对这些管道化请求的响应,以保证客户端能够区分出每次请求的响应内容。这就导致了假如服务端在处理一个请求时耗时比较长,那么后续请求的处理都会被阻塞住,会导致客户端迟迟收不到数据,这称为「队头堵塞」--在HTTP2中解决。
3、缓存控制
HTTP/1.1 在 HTTP/1.0 基础之上,增加了一些请求响应头,以更好的实现对缓存的控制。
- 新增 Cache-Control 代替原先的 Expires;
- 新增 If-None-Match 和 Etag 代替原先的 If-Modified-Since和 Last-Modified 。
4、断点续传
利⽤ HTTP 消息头使⽤分块传输编码,将实体主体分块传输。
三、HTTP/2.0
1、头部压缩
HTTP/1.1 中的请求头携带大量信息,而且每次都要重复发送,即使是同样的内容,每次请求都需要附带,这会造成性能的损耗。HTTP/2 进行了优化,引入了头信息压缩机制。
客户端和服务器同时维护一张头信息表,高频出现的字段会存入这个表,生成一个索引号。发送报文时直接使用索引号替代字段。另外,索引表中不存在的字段使用压缩。
同时,多个请求中,如果请求头相同,则后续请求只需要发送差异的部分,重复的部分无需再发送。
2、二进制帧
在HTTP/2中,在应用层(HTTP2.0)和传输层(TCP或者UDP)之间加了一层:二进制分帧层。这是HTTP2中最大的改变。HTTP2之所以性能会比HTTP1.1有那么大的提高,很大程度上正是由于这一层的引入。
在二进制分帧层中,HTTP/2会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码。这种单连接多资源的方式,减少了服务端的压力,使得内存占用更少,连接吞吐量更大。而且,TCP连接数的减少使得网络拥塞状况得以改善,同时慢启动时间的减少,使拥塞和丢包恢复速度更快。
3、多路复用
在 HTTP/2 中定义了流(Stream)的概念,它是二进制帧的双向传输序列,一个数据流对应着一个完整的请求-响应过程,在同一个请求响应过程中,往返的帧会分配一个唯一的流编号(Stream ID)。
在流的支持下,HTTP/2 可以在一个 TCP 连接中传输多个请求或响应,而不用按照顺序一一对应(即实现多路复用),因为它们属于不同的流,所发送的帧头部都会携带 Stream ID,可以通过此 Stream ID 有效区分不同的请求-响应。
因而 HTTP/2 解决了 HTTP/1.1 的『队头阻塞』问题,多个请求 - 响应之间没有了顺序关系,不需要排队等待,降低了延迟,大幅度提高了连接的利用率。
4、服务器主动推送
在 HTTP/1.1 中,只能客户端发起请求,服务器对请求进行响应。而在 HTTP/2 中,服务端可以主动给客户端推送必要的资源,以减少请求延迟时间。
比如当客户端向服务器请求一个 HTML 文件后,服务器除了将此 HTML 文件响应给客户端外,还可以提前主动将此 HTML 中所依赖的 JS 和 CSS 文件推送给客户端,这样客户端在解析 HTML 时,无需耗费额外的请求去得到相应的 JS 和 CSS 文件。
四、HTTP/3.0(QUIC 协议)
1、 无队头阻塞
HTTP/2 通过多路复用解决了 HTTP1.1 的『队头阻塞』问题,但其只是解决了 HTTP 这一层面的『队头阻塞』问题,底层仍然采用的 TCP 连接,HTTP/2 并没有解决 TCP 的『队头阻塞』问题。
TCP 是可靠的、面向字节流的协议。HTTP/2 的多个请求虽然可以跑在同一个 TCP 连接中,但如果出现丢包现象,TCP 就需要进行重传,这可能就会导致整个 TCP 连接上的所有流阻塞,直到丢的包重传成功,这就是 TCP 的『队头阻塞』问题。
为了解决此问题,HTTP/3 底层不再使用 TCP,而是采用 UDP!而 UDP 是无连接的,多个流互相独立,之间不再有依赖,因而即使某个流发生了丢包,只会对该流产生影响,并不会使得其他流阻塞!
这时候有的小伙伴可能会问了,HTTP/3 底层不采用 TCP,那怎么保证可靠传输呢?答案就是 HTTP/3 在应用层自己重新实现了可靠性机制。也就是说,HTTP/3 将原先 TCP 协议提供的部分功能上移至 QUIC,而且进行了改进。