高性能浏览器-HTTP 2.0

HTTP 2.0 将会使应用程序更快、更简单、并且更健壮。HTTP 2.0的首要目标通过请求-响应多路复用,报头压缩,优先级控制、服务器推送 来减少延时。为了达到这个目的,HTTP 2.0需要支持大量的路I量控制、错误异常处理以及协议升级机制。
HTTP 2.0 没有改变http1.x中methods, status codes, URIs, header fields这些元数据的语义。但是改变这些数据的传输方式。

HTTP 2.0 发展历史以及与SPDY关系

spdy 是google 在2009年中开发的实验性的协议,旨在通过解决HTTP 1.1中一些性能限制以降低网页的加载时间,它的大概要达到的目标有:
  • 降低50%的页面加载时间
  • 不要站点维护人员进行内容改变
  • 简化部署复杂度,避免网络拓扑变化
  • 与开源组织合作
  • 搜集实验数据验证该协议

提出该协议后没多久,很快谷歌就公布是SPDY实验结果以及源码;
2012年,包括chrome,firefox opera等其他站点都以及支持了SPDY;同年, HTTP Working Group已经准备将SPDY吸收到HTTP 2.0的官方标准中,之后HTTP-WG提出多次草案:
• March 2012: Call for proposals for HTTP 2.0
• September 2012: First draft of HTTP 2.0
• July 2013: First implementation draft of HTTP 2.0
• April 2014: Working Group last call for HTTP 2.0
• November 2014: Submit HTTP 2.0 to IESG as a Proposed Standard

设计和技术标准:

二进制帧
HTTP2 性能提升的核心是全新的二进制帧分层,客户端和服务端必须使用新的二进制编码方式同对端通信,下图描述了http消息在客户端和服务端间如何分装和传输:
二进制帧层只设计在socket收发层和HTTP层之间, 对http原来的语义,比如verbs,method和报头没有影响,但是在传输过程的编码方式不同,比如http1.x中使用的换行符,在http2通信中则被拆成更小的二进制消息和帧;

流,消息和帧
流:
一个tcp连接内的双向字节流;

消息:
一个对应着逻辑消息的完整的 一系列帧;

帧:
HTTP 2.0 最小的传输单位,每个帧都包含一个帧头,标识了每个帧属于哪个流;

HTTP2.0的通信是在一个tcp连接中进行的,每个连接可以包含人一个流。相应的,每个流通过消息通信,每个消息由帧组成,流之间可以相互交错并且通过帧头中的流标识进行重组。


HTTP 2.0 主要特征 总结:

  • 所有通信只在一个TCP连接中进程
  • 流在连接中是一个虚拟的通道,每个流携带者双向的信息。每个流程有着唯一的id (1, 2, …, N).
  • 消息是一个逻辑的http消息,比如请求或者响应,它们由一个或者多个帧组成。
  • 帧是最小的通信单位,携带者指定的数据,比如http报头或者负载等。

简单的说,HTTP 2.0将http协议拆分成了多个独立的帧,每个帧对应着一个逻辑的流。一个tcp连接中每个流可以并行的进行传输。


请求响应多路复用
HTTP/1.x 中,客户端可以通过使用多tcp连接让请求并行,但是请求是按顺序发送,同一个时间只能有一个响应返回。这种方式更不利的地方是,在http层产生了线头阻塞(只要某个响应卡住,其他相应也会卡住),另外也无法充分利用tcp的最大性能(每个连接都要通过慢启动方式来增大窗口来提高吞吐)

HTTP2.0 引入帧的概念消除了这个限制,通过将http消息拆成独立的、可交错的、可重组的帧,让所有的请求和响应都可以多路复用。




如上图,客户端发送一个 DATA frame (stream 5)给服务端,服务端为流1和流3发送一系列交错的帧给客户端。如此,就有三对 请求-响应 在并行的传输了。

将http消息拆分成了多个独立、可交错、可重组的帧,是http 2.0最大改进; 这些特性带来如下好处:
  •  让请求和响应多路复用,而不用担心线头阻塞问题
  • 只要用一个tcp连接就可以进行多个请求-响应通信,降低系统负载;
  • 降低页面加载时间,减少不必要的延时


请求优先级

HTTP消息可以拆分成多个独立帧,帧发送的顺序将会影响应用程序的性能。为了控制帧顺序,每个流都可以赋予一个31位的优先级。
• 0表示着最高优先级
• 2^31 - 1 表示最低优先级

客户端和服务端可以应用不同的策略去用于控制流、消息和帧,服务器可以根据CPU、内存、带宽来标识优先级;如果响应数据已经到达,应该提升优先级发送给客户端。

单TCP连接
有了帧的特新,服务端和客户端只要保持一个长连接,就可以完成请求-响应多路复用,带来的好处是,减少socket的数量,减少内存使用,更大的tcp吞吐,减少网络拥塞,减少慢启动带来的影响。大多数的http消息都是简短的,突发的,只用一个连接能更充分使用tcp性能(但只使用一个连接的HTTP 2.0 ,不能缩短网络延时(受限光速),但能提高网络吞吐率以及减少不必要的消耗);

HTTP 2.0 使用单连接,也有一些潜在的缺点:
  • 单连接解决了HTTP层的线头阻塞,但没有解决tcp层的线头阻塞(反而比多连接影响更大);
  • 如果没有启用window scaling特性(窗口最大只有64k了),带宽延迟积将会限制连接吞吐率;
  • 当发生丢包,拥塞窗口减小,连接的吞吐率会大大降低;

虽然性能过于依赖TCP和网络,但是实际实验过程中,使用单连接性能仍然比多连接好许多。HTTP 2.0解决了许多性能瓶颈,但是TCP将会是最后一个瓶颈。关于tcp优化的解决方案有 TCP Fast Open, Proportional Rate Reduction, increased initial congestion  window等等。

流量控制
单连接会引起多路复用产生对共享tcp资源的竞争,虽然优先级策略解决了资源的发送顺序,但不能很好解决多流之间的流控问题。因此,HTTP 2.0 引入了一个简单的机制来解决 多流间的流控问题。

  • 流控是hop by hop,不是end to end
  • 流控是基于window update帧,接收端通告对端在这条流或者整个链接中它将接收多少字节
  • 流控通过WINDOW_UPDATE帧更新,其中指定了流id和窗口增大值
  • 流控具有方向的,接收端可以为每个流选择设置任意大小窗口大小
  • 流控可以被接收端禁止,可以是一条流也可以是整个连接。

当HTTP 2.0连接建立是,两端会交换setting帧,其中包含了窗口大小。当然任意一端也可以为某条流或者整个链接禁止流控功能。Tcp的窗口控制不能基于每个流来控制,这也是HTTP 2.0 需要流控的原因。
HTTP 2.0协议没有指定具体算法、值或者window update何时发送,实现中可以根据使用情况和性能来设置。

服务端推送

HTTP 2.0 有个强大功能,可以对一个请求发送除了对应的响应外,还会发送多个其他相关文件响应。多余的响应是和请求是相关的。服务端可以把请求的其他关的资源推送的客户端,而不用等待客户端一一请求。

服务端推送带来了一下几个好处:
  • 推送资源可以被客户端缓存
  • 推送资源可以被客户端拒绝
  • 推送资源可以被多个页面复用
  • 推送资源可以被服务端优先处理

PUSH_PROMISE
所有推送流都是通过 PUSH_PROMISE帧启动, PUSH_PROMISE帧只是包含了推送资源的http报头。
客户端收到了推送帧,客户端可以选择拒绝该流(比如该资源已经被客户端缓存)。
服务端必须遵循请求-响应的规则,只有收到请求后才可以发送推送帧,而不能任意发送推送帧。推送内容必须在它本身请求之前被发送。

报头压缩
HTTP传输携带着一些列报头,这些报头描述了需要传输的资源以及资源的属性,在HTTP/1.x中这些语义都是用明文来表示并且这些报头让每个请求会增加500-800个字节大小,如果携带了cookies将会增加上千字节的数据。为了减少这些报头,并且提升性能,HTTP/2.0压缩了这些报头:

  • 不用为每个请求和响应传输相同的数据,HTTP 2.0使用了 "header table",同时在服务端和客户端引用和存储这些key-value 对。
  • Header table 在整个连接过程有效,客户端和服务端也可以进行增量更新。
  • 一个新的key-value 可以添加到表的末端,也替换掉表中的旧值。

如此,收发两端就可以知道已经发送了那些报头以及对应的value,这样新报头就可以根据就得报头信息,发送不一样的键值对信息即可,如下图:


这个例子中,第二个请求只要发送发生改变的path报头,如此减少了重复报头发送量。一般情况下键值对在整个连接过程几乎不发生改变(如user-agent, accept header)。相同报头只要发送一次,如果报头都未发生变化,请求将继承之前请求的报头信息。

HTTP 2.0 升级和发现
切换到HTTP 2.0不可能在一夜之前发生,有数百万计的服务器,数亿计的客户端需要更新浏览器或者网络库。
http 2.0支持兼容模式的切换方式,客户端需要在连接启动阶段判断服务端是否支持HTTP 2.0; 需要考虑一下三种场景:

  • TLS 和ALPN方式启动https连接
  •  序言方式启动http连接
  • 没有序言方式启动连接

ALPN 用于发现HTTPS连接是否支持HTTP 2.0的TLS扩展头,可以在HTTPs连接握手阶段判断是否支持HTTP2.0,以减少延时。
明文方式启动的http将会费事些,HTTP/1.x 和HTTP 2.0都运行在80端口,没有其他信息可以用于判断是否支持HTTP2.0
客户端将会用一种 Upgrade 升级机制来协商出一种合适的协议:
    GET /page HTTP/1.1
    Host: server.example.com
    Connection: Upgrade, HTTP2-Settings
    Upgrade: HTTP/2.0     (1)
    HTTP2-Settings: (SETTINGS payload)  (2)

    HTTP/1.1 200 OK     (3)
    Content-length: 243
    Content-type: text/html
    (... HTTP 1.1 response ...)

    (or)
    HTTP/1.1 101 Switching Protocols    (4)
    Connection: Upgrade
    Upgrade: HTTP/2.0
    (... HTTP 2.0 response ...)

  1. http 1.1请求携带 HTTP2.0升级报头
  2. HTTP2.0 SETTING携带 Base64编码的URL
  3. 服务器拒绝升级,返回http 1.1响应
  4. 服务器接受HTTP 2.0升级,切换到新框架

二进制帧简介

带长度表示的二进制帧是HTTP 2.0的核心改进点。与 HTTP/1.x使用换行分隔符相比,二进制帧提供了更加简洁的方式,代码上也更加简单和高效。一旦HTTP 2.0连接建立后,客户端和服务端通过帧来通信。每个帧都带有一个8字节的头部,包含了帧的长度和帧类型,一个标志位和一个31位的流id。


  • 16位长度位,一个帧最大可以携带2^16 -1  长度数据,不包括8字节帧头
  • 8位类型
  • 8位标志位
  • 一个保留位(一直为0)
  • 31位流唯一标识

有以下几种帧类型:
DATA       :数据帧用于传输HTTP body消息
HEADERS  : 报头帧 由键值对(name-value)组成,用来打开一个流
PRIORITY   :  优先级帧 明确了发送者建议的流的优先
RST_STREAM :终止帧用于终止一条流
SETTINGS :设置帧 设置两端通讯的参数
PUSH_PROMISE推送承诺帧 用来告知接收端准备稍后推送数据  
PING :ping帧 用于衡量两端rtt
GOAWAY : 超时帧用于 通知接收端不要在当前连接上创建新流。但之前的流仍可以继续处理
WINDOW_UPDATE窗口更新帧 用来实现流量控制,包含对单个流或整个连接的控制,但只能影响DATA帧的传输
CONTINUATION:  延续帧 用来延续一个报头块片段。


启动一条新流
应用程序在发送数据前,必须创建一条流,指明优先级或者发送报头等。HTTP 2.0中,客户端和服务端都可以启动新流:

  • 客户端通过发送报头帧启动一个请求,报头帧包含一个流ID,一个可选的31位优先级和一系列http报头键值对。

  • 服务端通过发送一个承诺推送帧来启动一个推送流,几乎和报头帧一样,但多包含了一个承诺流的id,取代爆头战中的优先级值


为了避免流id冲突,客户端启动新流只取奇数id,服务端启动新流只取偶数id;流的元数据和应用程序数据是分开发送的,客户端和服务端可以使用不同的优先级,比如流控可以使用更高的优先级,流控只用于数据帧

数据发送
流一旦创建并且报头已经发送, http数据就可以发送了,数据可以拆成多个数据帧发送,最后一个数据帧打上 END_STREAM标记。

严格来说,数据帧长度可以达到2^16-1( 65535) ),但是为了避免线头阻塞, HTTP 2.0协议规定最大长度是2^14 -1 ( 16383),超过最大值就要拆成多个数据帧。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值