HTTP/2 的实现的主要功能包括通过支持完整的请求与响应复用来减少延迟,通过有效压缩 HTTP 标头字段将协议开销降至最低,增加对请求优先级和服务器推送的支持
您很可能注意不到任何区别:所有新的低级分帧由客户端和服务器为您执行
理解以下的概念有助于学习 HTTP/2
数据流:已建立连接内的双向字节流,可以承载一条或多条消息
消息:与逻辑请求或响应消息对应的完整的一系列帧
帧:HTTP/2通信的最小单位,包含帧头
一个 TCP 连接上承载任意数量的数据流,每个数据流承载双向消息,每条消息包含一个或多个帧,帧是最小单位承载特定的数据
在应用层新增一个二进制分帧层,用来处理所有 http/2 新增的特性,对于通过 http/2 传输的信息细分为消息和帧,使用二进制格式编码。
请求与响应复用、服务器推送、标头压缩等。
HTTP/2 的消息都是在一个 TCP 连接内完成,通过把消息分成一些列的帧,把这些帧交错传输从而达到复用的目的,每个帧都包含数据流标识符,接收端根据其在重新组装成一条消息。
数据流优先级,因为在一个连接中有多个帧交错传输,为了保证传输优先级高的资源,通过给数据流设置权重和依赖关系来实现传输的优先级。
每个来源一个连接,因为请求与响应的复用,所以通过 HTTP/2 的数据流都可以在一个 TCP 连接传输,所以只需要每个来源一个连接即可,HTTP/2 的链接都是永久的。
如图所示可以通过 Network 工具查看请求的 Connection ID 会发现同一个源下面使用 HTTP/2 的请求都是同一个 ID
服务器可以对一个客户端请求发送多个响应。有别于 HTTP/1.x 定义的一个请求一个响应,HTTP/2 下服务器可以主动推送内容给客户端,这主要考虑场景是现在的一个网络应用会包含多种资源,可以通过服务器提前推送这些资源,从而减少客户端再次发起资源请求的延迟时间。
所有服务器推送数据流都是通过 PUSH_PROMISE 帧发起,客户端接受到后可以拒绝、缓存、复用
压缩请求与响应标头的元数据减少传输的字节大小,通过 HPACK 压缩格式,有别于 HTTP/1.x 中每次请求都带上所有的请求头信息,HTTP/2 通过对传输的标头字段编码后传输索引值,然后通过服务端和客户端维护的索引列表来解码重构标头键值对。
对于如何查看一个请求是否开启 HTTP/2,可以通过查看请求响应头,":method" 等包含以冒号开头的标头都可以认为是 HTTP/2
简单介绍了 HTTP/2 的一些概念以及一些新特性,总结下来 HTTP/2 主要特性,请求与响应复用、标头压缩、服务端推送。
了解到了一些特有的关键词,数据流、消息、帧、二进制分帧层,每个来源一个连接,霍夫曼编码
http 1.0 规定浏览器与服务器保持较短时间的链接,浏览器每次请求都和服务器经过三次握手和慢启动(基本思想是当TCP开始传输数据或发现数据丢失并开始重发时,首先慢慢的对网路实际容量进行试探,避免由于发送了过量的数据而导致阻塞)建立一个TCP链接,服务器完成请求处理后立即断开TCP链接,而且不跟踪每个浏览器的历史请求。
注意:由于http 1.0每次建立TCP链接对性能的影响实在是太大,http1.1实现持久化链接之后,又反向移植到http 1.0上,只是默认是没有开启持久链接的,通过http的header部分的 Connection: KeepAlive 来启用)
请求队列的第一个请求因为服务器正忙(或请求格式问题等其他原因),导致后面的请求被阻塞。
一个TCP链接可以传送多个http请求和相应,减少了TCP建立链接和关闭链接的消耗。另外http1.1允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能 够区分出每次请求的响应内容。
不使用管道的http请求,在使用持久链接时,必须严格满足先进先出的队列顺序(FIFO),即发送请求,等待响应完成,再发送客户端队列中的下一个请求。管道可以让我们把 FIFO 队列从客户端(请求队列)迁移到服务器(响应队列),即客户端可以并行,服务端串行。客户端可以不用等待前一个请求返回,发送请求,但服务器端必须顺序的返回客户端的请求响应结果。
a. 一个请求响应阻塞,就会阻塞后续所有请求
b. 并行处理请求时,服务器必须缓冲管道中的响应,从而占用服务器资源,如果有个响应非常大,则很容易形成服务器的受攻击面;
c. 响应失败可能终止 TCP 连接,从页强迫客户端重新发送对所有后续资源的请求,导致重复处理;
d. 由于可能存在中间代理,因此检测管道兼容性,确保可靠性很重要;
e. 如果中间代理不支持管道,那它可能会中断连接,也可能会把所有请求串联起来。
http1.1 在客户端排队所有请求,然后通过一个TCP持久链接,一个接一个的发送请求(如果有http管道还必须顺序等待服务端的顺序返回结果)。但实际中,浏览器的开发时不会这么笨,浏览器允许我们打开N个TCP链接(大多说浏览器是6个TCP链接,这个数字越大,客户端和服务器的资源占用越多,这个数据也只是感觉安全的数字而已)。
1.更多的套接字会占用客户端、服务器以及代理的资源,包括内存缓冲区和 CPU时钟周期;
2.并行 TCP 流之间竞争共享的带宽;
3.由于处理多个套接字,实现复杂性更高;
4.即使并行 TCP 流,应用的并行能力也受限制。
因此使用多个TCP链接只是权宜之计,后续的http 2.0支持多路复用,很好的解决了上述问题。
举例:
a. 支持Host请求:
b. Connection: 请求头的值为Connection时,客户端通知服务器返回本次请求结果后保持连接;Connection请求头的值为close 时,客户端通知服务器返回本次请求结果后关闭连接
c. 支持断点续传:
d.身份认证:
e.状态管理:
f. 缓存处理:
域名分区是思想是将原来集中到一个服务器上的资源分布到多个服务器上,这样就可以突破浏览器的链接限制(一般是6个),提高并行能力。
代价:
2.必须手工分离一台主机上的资源到多台;.
实际实践中,效果并不是很明显,反而导致被滥用。
目前所有的header请求都是以没有经过压缩的纯文本的形式发送(通常会有600`1000字节),而通常使用的http请求body却很少(10~200字节),和header相比,显得很少,特别是在使用了cookie之后,这样的矛盾就更加突出,因此要减少header的数据。
即将需要多次才能获取的文件或资源组合并成一个,通过一次网络请求获取。这样减少了协议的开销,间接地将服务器端的管道思维移植到了客户端。缺点:增加复杂性,更缓存带来负担,页面的分步显示,改成一次显示,在网络慢的时候影响用户体验。
即将资源嵌入文档(通过URI嵌入图片,音频或PDF),可以减少请求次数。嵌入资源作为页面的返回一部分一次返回,即如果在多个页面中都嵌入同样的资源,那么这个资源将会随着每个页面的加载而被加载,从而增大每个页面的总体大小,如果嵌入资源被更新,客户端只能重新获取有效的资源。
实践:一般只考虑嵌入1~2KB一下的资源
2.如果文件很小,但需要在多个页面中重用,应该考虑集中打包;
HTTP 2.0把解决性能问题的方案内置在了传输层,通过多路复用来减少延迟,通过压缩 HTTP首部降低开销,同时增加请求优先级和服务器端推送的功能。
多路复用允许同时通过单一的 HTTP 2.0 连接发起多重的请求-响应消息,即所有HTTP 2.0 连接都是持久化的,而且客户端与服务器之间也只需要一个连接即可,所有数据流共用同一个连接 ,减少了因http链接多而引起的网络拥塞(在 HTTP1.1 协议中,同一时间,浏览器会针对同一域名下的请求有一定数量限制),解决了慢启动针对突发性和短时性的http链接低效的问题。
即应用层(HTTP)和传输层(TCP or UDP)之间增加一个二进制分帧层,因此在多向请求和响应时,客户端和服务器可以把HTTP消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来,解决了http 1.*的对手阻塞问题。
http 2.0支持DEFLATE和HPACK 算法的压缩。
指客户端请求之前发送数据的机制,在 HTTP 2.0 中,服务器可以对客户端的一个请求发送多个响应。
HTTP 2.0 使用一个31比特的优先值,0表示最高优先级, 2(31)-1表示最低优先级,服务器端就可以根据优先级,控制资源分配,优先处理和返回最高优先级的请求帧给客户端。
参考文献:
1.面试时如何优雅的谈论HTTP/1.0/1.1/2.0( http://www.jianshu.com/p/52d86558ca57 )
HTTP是应用层协议,是基于TCP底层协议而来。
TCP的机制限定,每建立一个连接需要3次握手,断开连接则需要4次挥手。
HTTP协议采用“请求-应答”模式,HTTP1.0下,HTTP1.1非Keep-Alive模式下,每个请求都要新建一个连接,完成之后立即断开连接。如果有新的请求,则要重新创建请求连接(HTTP协议为无连接的协议)。
这样不免造成了网络传输数据一定的延迟,1999年推出HTTP1.1,虽然可以通过设置延迟时间,让连接延迟关闭。但仍然有线头阻塞,max-connection最大连接限制了并行请求数量等痛点,难以应对日益增长的大数据实时传输。
新一代HTTP2.0协议应运而生,提高HTTP应对高并发场景下的数据传输能力。
提出管道化方案解决连接延迟,服务端可设置Keep-Alive来让连接延迟关闭时间,但因为浏览器自身的Max-Connection最大连接限制,同一个域名 (host) 下的请求连接限制(同域下谷歌浏览器是一次限制最多6个连接),只能通过多开域名来实现,这也就是我们的静态资源选择放到CDN上或其它域名下,来提高资源加载速度。
pipelining方案需要前后端支持,但绝大部分的HTTP代理器对pipelining的支持并不友好。
pipelining只支持GET/HEAD方式传送数据,不支持POST等其它方式传输。
HTTP是无状态的,客户端/服务端只能通过HEAD的数据维护获取状态信息,这样就造成每次连接请求时都会携带大量冗余的头部信息,头部信息包括COOKIE信息等。
HTTP1.X是超文本协议传输。超文本协议传输,发送请求时会找出数据的开头和结尾帧的位置,并去除多余空格,选择最优方式传输。如果使用了HTTPS,那么还会对数据进行加密处理,一定程度上会造成传输速度上的损耗。
pipelining通过延迟连接关闭的方案,虽然可同时发起对服务端的多个请求,但服务端的response依旧遵循FIFO(first in first out)规则 依次返回。
举个例子客户端发送了1、2、3、4四个请求,如果1没返回给客户端,那么2,3,4也不会返回。这就是所谓的线头阻塞。高并发高延迟的场景下阻塞明显。
以上三种三种方法虽然能使HTTP1.X协议传输速度提高,但也有对应的不足。
了解完HTTP1.1的痛点,接下来就是我们新一代的HTTP协议HTTP2.0
SPDY是2012年谷歌推出的是基于SSL/TLS的传输协议,SPDY有降低延迟,多路复用,头部压缩,服务端推送等特点,这些特点也称为了后续HTTP2.0的功能基石,HTTP2.0是SPDY/3 draft的优化版。
HTTP2.0 与 SPDY的区别:
(一个域只要一个TCP连接)实现真正的并发请求,降低延时,提高了带宽的利用率。
客户端/服务端进行渐进更新维护,采用HPACK压缩,节省了报文头占用流量。
两端会共同维护一个head list,每次请求时都会进行检查。
该list包括:
每个流都有自己的优先级别,客户端可指定优先级。并可以做流量控制。因为HTTP2.0的传世允许请求并发,但是应用场景中我们要处理一些主要文件的优先级权重,以及资源模块依赖等。所以我们可通过设置优先级来提高主要文件的权重,使其优先加载请求。
请求不是来自客户端“明确”的请求,是从服务端PUSH_PROMISE帧中提供。例如我们加载index.html, 我们可能还需要index.js, index.css等文件。传统的请求只有当拿到index.html,解析html中对index.js/index.css的引入才会再请求资源加载,但是通过服务端数据,可以提前将资源推送给客户端,这样客户端要用到的时候直接调用即可,不用再发送请求。
HTTP2.0 传输协议采用二进制协议,区别与HTTP1.X的超文本协议。更易于帧,数据包的发送接收。HTTP2.0是运行在TCP连接上的应用层协议,接受服务器或发送请求时,会自动将头部信息/request body分成HEAD帧和DATA帧。
客户端/服务端发送/接收数据时,会将数据打散乱序发送,接收数据时接收一端再通过streamID标识来将数据合并。
HTTP2.0理论上支持明文HTTP传输,但因为其前身SPDY是在TLS上,他们的主人Google 和 Firefox 都支持TLS架构,所以需要搭建HTTP2.0 + TLS成了标准。
参考文档
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)