49-http-2-版本历史

概述

现在使用的HTTP协议有几个版本。HTTP程序要尽量强健地处理各种不同的HTTP协议变体。

http请求是要通过tcp去建立连接,并在此之上发送数据,http只有请求和响应这个概念,没有链接这个概念。

http1.0的时候,在http request的时候,在里面发起三次握手,创建TCP链接,然后再发起请求,请求结束后则关闭TCP链接。

http1.1可以通过声明这个链接,可以保持在那里,后面就不需要三次握手开销;但是在一个tcp连接上同时只能发送一个请求,所以在有并发请求的时候只能建立多个tcp连接。

HTTP2中是可以在一个TCP连接同时中发送多个HTTP请求。

版本

HTTP/0.9

特点

HTTP/0.9只支持GET方法。


不支持多媒体内容的MIME类型、各种HTTP首部,或者版本号。

服务器发送完毕,就关闭TCP连接。

命名

HTTP 于 1990 年问世。那时的 HTTP 并没有作为正式的标准被建立。

实含有 HTTP1.0 之前版本的意思,因此被称为HTTP/0.9。

HTTP/1.0

特点

HTTP/1.0添加了status code、header(各种HTTP首部)、版本号、一些额外的方法。

多字符集支持、多部分发送、权限、缓存等。


每次请求都打开一个新的TCP链接,收到响应之后立即断开连接。

命名

HTTP 正式作为标准被公布是在 1996 年的 5 月,版本被命名为HTTP/1.0,并记载于 RFC1945

虽说是初期标准,但该协议标准至今仍被广泛使用在服务器端。

HTTP/1.1

特点

持久化

HTTP/1.1 默认开启持久连接,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟。

在1.0版本中,每进行一次HTTP通信就要断开一次TCP连接。

TCP连接的新建成本很高,频繁地打开关闭会极大地增加开销,影响性能。

于是在1.1版本中引入持久连接的方法。其特点就是任意一端没有明确提出断开连接,则保持TCP连接的状态。

管线化

HTTP/1.1增加了pipeline支持。

管线化的连接建立在持久化连接的基础上,且响应需要顺序返回。

非管线化的请求:如上图中第一幅

客户端发送一个请求之后,必须等待服务器响应之后才能发送下一个请求,不能同时并行发送多个请求。


管线化的请求:如上图中第二幅

客户端一次性发送多个请求,不用等待服务器响应就可以发送下一个请求。


队头阻塞

管线化:如上图中第三幅

http1.1规定,服务器端的响应的发送要根据请求被接收的顺序排队,即先接收到的请求需要先响应回来。所以当第一个请求阻塞后,后面的请求都需要等待。

请求可以并行发出,但是响应必须串行返回。后一个响应必须在前一个响应之后。原因是,没有序号标明顺序,只能串行接收,阻塞发生在服务端,http响应阻塞。

非管线化: 如上图中第一幅

后一个请求必须在前一个响应之后发送,发生在客户端,http请求阻塞。


HTTP2多路复用:如上图中第四幅

解决第二个请求不被第一个请求阻塞,最好的办法就是来两个TCP连接。传统上浏览器也是这么干的。但是TCP要握手,这个效率低,所以HTTP2把多个这种请求流塞到一个TCP连接里面,这样的连接复用方式就提高了效率,又节省了连接握手。

为了解决HTTP1.1管线化队头阻塞的问题,http2中,将多个请求复用到同一个tcp通道中,通过二进制分帧并且给每个帧打上ID 去避免依次响应的问题,对方接收到帧之后根据 ID 拼接出流,这样就可以做到乱序响应从而避免请求时的队首阻塞问题。

但是HTTP2没有完全解决队头阻塞问题,因为实际中TCP的连接buffer有限,一个响应又慢,又大的请求会把链接buffer完全占满,导致buffer阻塞,从而导致跟队头阻塞一样的效果。

增加HOST字段

HTTP/1.1 的请求消息和响应消息都必须包含Host头部,以区分同一个物理主机中的不同虚拟主机的域名。

1.0版本中,认为每台物理服务器对应唯一的IP地址。所以,在1.0版本中是没有主机名这个概念的。但随着Web技术的发展,一台物理服务器可以存在多个虚拟主机,他们共享同一个IP地址。为了解决这个问题,HOST字段应运而生。

命名

1997 年 1 月公布的 HTTP/1.1 是目前主流的 HTTP 协议版本。当初的标准是 RFC2068,之后发布的修订版 RFC2616 就是当前的最新版本。

HTTP/2.0

特点

二进制分帧

在HTTP协议2.0中,应用层和传输层之间会多一个二进制分帧层。在二进制分帧层上,HTTP 2.0 会将所有传输的信息分割为更小的帧,并对它们采用二进制格式的编码 。之前HTTP1.x版本中的HTTP报文首部信息会被封装到Headers帧,而我们的HTTP报文主体则封装到Data帧里面。原先我们是以HTTP报文为单位传输的,现在HTTP报文被拆成了多个帧的形式,并且这些帧可以乱序发送,我们只需根据每个帧首部的流标识符就可以重新完成组装。这样极大提升了HTTP的性能。

多路复用

HTTP/2.0支持多路复用,就是在一个 TCP 连接中可以存在多条流,也就是可以发送多个请求,服务端则可以通过帧中的标识知道该帧属于哪个流(即请求),通过重新排序还原请求。多路复用允许并发的发起多个请求,每个请求及该请求的响应不需要等待其他的请求或响应,避免了队头阻塞问题。这样某个请求任务耗时严重,不会影响到其它连接的正常执行,极大的提高传输性能。

头部压缩

每次HTTP请求都会有一个请求首部,这个首部放到一些重要信息,比如Cookie、User Agent之类的字段,这些字段每次请求都是一样的,但还必须要带上。这就造成了一些不必要的浪费。2.0中就优化这一点,引入首部压缩机制,客户端和服务端会维护同样一张首部信息表,每次请求只要发送索引号就可以了,不必带上请求首部上冗余的key-value,极大地减少了不必要的浪费。

服务端推送

在2.0之前的版本中,服务端是属于被动一方,只有客户端发送请求,服务端才能发送资源。2.0协议中,服务端可以主动地向客户端发送资源。例如:客户端请求一个html,里面所需要的js和css完全不需要客户端解析完html之后再去请求这些内容那么麻烦,服务端可以在客户端请求html的时候一起回传过来。

推荐阅读

阮一峰

HTTP 协议入门