Http 2.0协议简介

  该文主要介绍为什么推出HTTP 2.0协议,以及HTTP2协议的主要概念是什么?

  今天,Http1.1已经变成了互联网主要的协议,在协议和基础设施上投入了巨资。当初HTTP协议诞生时曾经被误以为是相当简单直接的协议,但是时间证明错了。1996年在RFC 1945中颁布的Http 1.0 有60页规定,RF2616描述的HTTP1.1只在三年后也就是1999年颁布,大幅增加到176页,HTTP1.1变得很大,包括许多细节、必要的和可选的配件。后来自然增长为一个软件生态系统,好像几乎没有什么没有实现过,但其实并不是,导致一个情况:开始很少用到的功能很少实现,而实现的功能以后却很少用到。最后,当客户端和服务器端开始增加这些功能以后就导致了互操作性问题,HTTP Pipelining是这样情况的主要例子。

  HTTP 1.1很难真正发挥TCP提供全部优点和强项,HTTP客户端和浏览器必须找到一个创造性的解决方案,以降低页面加载时间。

  其他试图替换TCP协议的尝试被证明不太可行,我们只能基于TCP和其上的协议继续努力。TCP能简单地更有效使用,以避免接受和发送更多数据导致的暂停。下面会突出这些要点。

  

传送数据大小和对象数量

  当前互联网网站首页数据量下载很大,达到1.9M,更重要的是首页上的对象元素平均有100多个,这100多个对象必须抓取完毕后才能显示整个首页页面。

 

延迟

  HTTP 1.1是对延迟非常敏感的,部分是因为HTTP Pipelining在面对大量并发用户时会显得力不从心,在过去几年中带宽大量增加,但是我们没有看到页面延时以同样级别降低,高延时链接比如目前移动技术使得你即使拥有高速连接情况下也很难获得好的快速Web体验。另外一个情况是,低延迟非常适合视频,比如视频会议 游戏和类似不是预先产生而是实时产生的流媒体或流数据。

 

堵塞的原因

  HTTP Pipelining是一种这样的技术,当在等待上一个请求响应的时候发送另外一个请求,这好像你走入了超市的收银台前排队队列,你无法确切知道排在你前面的人能够快速付款购买完成,还是发生一堆恼人的烦事在那里纠缠不清,这就是堵塞的源头。

  所以,你得仔细地选择一个排队队伍,有时你相信你选择了一个正确的队伍,能够快速轮到你,但是有时你不得不在几个队伍之间切换排队。

  创建一个新的排队是有性能和资源损耗的,而且不是可扩展的,这并没有完美解决方案。即使今天大部分桌面Web浏览器默认还是失效HTTP Pipelining。点按此可以了解这方面更多信息。

 

克服延迟的办法

  Spriting 是一种前端页面的处理方式,将多个小图片合成一张大图,然后,使用javascript或CSS在显示时将这张大图分割成多个小图,这样降低抓取多个小图造成的高延迟。当然这种办法也有缺点,如果只要想显示一个或两个小图,而不是很多小图都想显示,这样做就麻烦了。

  Inlining内联是另外一个避免发送单独图像的方式,使用CSS文件中嵌入的URL,优缺点和Spriting类似:


.icon1 {

  background: url(data:image/png;base64,<data>) no-repeat;
}

.icon2 {
   background: url(data:image/png;base64,<data>) no-repeat;

}

   Concatenation串联类似前面两个技术,一个大型网站需要很多Javascript文件,前端工具会帮助开发者将这些小文件融入到一个大文件中,这样做的缺点是,当其中一个文件小修改时,整个文件都需要重新加载。

  Sharding是将你的服务尽可能分离成不同的单独主机上,看上去很疯狂,但是其实很简单,HTTP 1.1规定一个客户端允许连接到每个主机最多两个,这样不违反规定的情况下,聪明的网站将使用两个主机名,能够降低页面的装载时间。不过,随着时间推移,规定中的限制已经去除,今天客户端可以用6-8个连接每个主机,但是使用这个技术实现大量连接还是有限制的。根据httparchive.org显示世界上大部分网站需要38个TCP连接来显示网站,这个数字还在缓慢增加。将资源或图片放在另外一个主机名中就不能使用任何cookie。

 

HTTP更新

  为什么不能使得协议变得更好,比如包括:

  1. 使得协议更少RTT敏感
  2. 解决pipelining和排队堵塞问题
  3. 让每个主机连接数量自由增长。
  4. 保留所有现有的接口,所有内容 URI格式和schema

 

起始于SPDY的Http2

  SPDY3协议是由Google开发的,虽然开放要求大家参加,但是很显然他们通过控制大部分浏览器实现能够获取很大的好处。专门负责Http协议的工作小组HTTPbis 是时候开始启动Http2工作了,SPDY已经被证明是一个可运行的方案,http2可以从SPDY/3草稿起步。

 

Http2

  Http2协议是一个二进制协议,二进制更易于frame(帧 数据包)的实现,Http2有十个不同frame定义,其中两个最基础的对应于HTTP 1.1的是Data数据和HEADE头部,其后将描述。

  frame是包含几个部分:类型Type, 长度Length, 标记Flags, 流标识Streamframe payload有效载荷。

  流标识是描述二进制frame的格式,使得每个frame能够基于http2发送,与流标识联系的是一个流,每个流是一个逻辑联系,一个独立的双向的frame存在于客户端和服务器端之间的http2连接中。一个http2连接上可包含多个并发打开的流,这个并发流的数量能够由客户端设置,这些流可能是打散了通过物理连接传输。

多路复用流Multiplexed stream

  假设两种火车代表不同的流,如下图:

http stream

然后,将它们排在一个连接上进行传输,如同行驶在单个铁轨上一样:

Http2连接可以承载数十或数百个流的复用,多路复用意味著来自很多流的数据包能够混合在一起通过同样连接传输,两列不同火车被混合在一起传输,当到达终点时,它们又被拆开组成两列不同的火车。

在HTTP1中你需要维持连接以便持续发送和接受数据,这导致数据拥挤和RTT浪费损耗,在HTTP2中,所有流都能时刻被切断提炼数据包。

 

优先权和依赖

   每个流都有自己的优先级别,会表明哪个流是最重要的,客户端会指定哪个流是最重要的,有一些依赖参数,这样一个流可以依赖另外一个流。

  优先级别可以在运行时动态改变,当用户滚动页面时,可以告诉浏览器哪个图像是最重要的,你也可以在一组流中进行优先筛选,能够突然抓住重点流。

 

头部压缩

  HTTP是一个无态协议,也就是说,每个请求必须携带更多细节,以便服务器能够识别从而服务这个请求,这些都无需服务器自己保存太多信息以及先前请求的元数据信息,HTTP2没有改变这个范式。但是这种方式会产生重复信息,当一个客户端向相同服务器请求许多资源时,像来自同一个网页的图像,将会有大量的请求看上去几乎同样的,这就需要压缩技术对付这种几乎相同的信息。

  HTTPS和SPDY的压缩被发现容易导致BREACH4和CRIME攻击。因此压缩不是一个简单的课题,HPACK6是HTTP/2的头部压缩。

 

随时复位

  HTTP1.1一个缺点是当HTTP信息有一定长度大小数据传输时,你不能方便地随时停止它,中断TCP连接的代价是昂贵的。使用HTTP2的RST_STREAM将能方便停止一个信息传输,启动新的信息,在不中断连接的情况下提高带宽利用效率。

 

服务器端推

  客户端请求一个资源X,服务器端判断也许客户端还需要资源Z,在无需事先询问客户端情况下将资源Z推送到客户端,客户端接受到后,可以缓存起来以备后用。

 

流程控制

  http2的每个独立流都有自己的流程控制flow controller,每个流两端都必须告诉对方自己有更多空间适合数据存放,另外一端只能允许发送更多数据直至流flow窗口被拓展,类似SSH工作风格,只有DATA frame是流程控制的。

 

本文是根据http://daniel.haxx.se/http2/翻译

H2O是性能超过Nginx的开源Http服务器