第186题:HTTP/2 对比 HTTP/1.1,特性是什么?是如何解决队头阻塞与压缩头部的?
队头阻塞与短连接/长连接无关,而是由 HTTP 基本的 请求-应答 模式所导致的:
- 因为HTTP规定报文必须 一发一收,这就形成了一共先进先出的串行队列。队列里的请求没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求被最先处理。
- 如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
引言
本文主要通过以下四个方面介绍,循序渐进走进HTTP/2:
HTTP/1.1发明以来发生了哪些变化?
近年来,如果你仔细观察那些最流行的网站首页所需要下载的资源的话,会发现一个非常明显的趋势:
正如下图所示,从 2011 年以来, 传输数据大小与平均请求资源数量不断持续增长,并没有减缓的迹象(绿色:传输数据大小,红色:平均请求资源数量):
自从 1997 年 HTTP/1.1 发布以来,我们已经使用 HTTP/1.x 相当长一段时间了,但近几年内容的爆炸式成长使得 HTTP/1.1 越来越无法满足现代网络的需求了
HTTP/1.1 协议的性能缺陷
1. 高延迟:页面访问速度下降
虽然近几年来网络带宽增长非常快,然而我们却并没有看到网络延迟有对应程度的降低,这主要是由于队头阻塞 (Head-Of-Line Blocking)问题导致
队头阻塞导致再打的带宽无法被充分利用
因此 人们尝试过以下办法来解决队头阻塞问题:
2. 明文传输:不安全
HTTP/1.1 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
3. 无状态:头部巨大切重复
由于 HTTP 协议是无状态的,每一个请求都得携带 HTTP 头部,特别是对于有携带 cookie 的头部,而 cookie 的大小通常很大,另外还有User Agent、Accept、Server等,通常多达几百字节甚至上千字节,但 Body 却经常只有几十字节
4. 不支持服务器推送
HTTP/1.1 不支持服务器推送消息,因此当客户端需要获取通知时,只能通过定时器不断地拉取消息,这无疑浪费大量了带宽和服务器资源。
HTTP/2 新特性
在 HTTP/1.x 中,为了性能考虑,我们会引入雪碧图、将小图内联、使用多个域名等等的方式,但还是有一些关键点无法优化,例如HTTP头部巨大且重复、明文传输不安全、服务器不能主动推送等,要改变这些必须重新设计 HTTP 协议,于是 HTTP/2 就出来了!
2015 年,HTTP/2 发布。HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法 / 状态码 / 语义都与 HTTP/1.x 一样。HTTP/2 基于 SPDY,专注于性能,最大的目标是在用户和网站间只用一个连接(connec-tion)。
从目前的情况来看,国内外一些排名靠前的站点基本都实现了 HTTP/2 的部署,使用 HTTP/2 能带来 20%~60% 的效率提升。
可以通过该链接直观感受下 HTTP/2 比 HTTP/1 到底快了多少: https://http2.akamai.com/demo
1. 二进制传输
在不改动 HTTP/1.x 的语义、方法、状态码、URI 以及首部字段….. 的情况下,HTTP/2 是如何做到「突破 HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量」的 ?
关键之一就是在应用层(HTTP/2)和传输层(TCP or UDP)之间增加一个二进制分帧层。
在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 HEADERS 帧,而相应的 Request Body 则封装到 DATA 帧里面,HTTP/2 数据分帧后,“Header+Body"的报文结构就完全消失了,协议看到的只是一个个"碎片”。
HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装
2. Header 压缩(HPACK)
HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
HTTP/2 对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
3. 多路复用
在 HTTP/2 中引入了多路复用的技术。多路复用很好地解决了浏览器限制同一个域名下请求数量的问题,同时也更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。
这一特性使得 HTTP 传输性能得到极大提升,主要体现在以下三个方面:
多工
HTTP/2 复用 TCP 连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"
数据流
HTTP/2 并行交错地发送多个请求 / 响应,请求 / 响应之间互不影响
因此,必须要对数据包做标记,指出它属于哪个请求 / 响应。
HTTP/2 将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2 可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
优先级
在 HTTP/2 中,每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。
4. 服务端 Push
HTTP/2 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。
常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。
这样就可以相对减少一点延迟时间。当然在浏览器兼容的情况下你也可以使用 prefetch 。
注意: 服务端可以主动推送,客户端也可以主动选择是否接收,如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收,另外,主动推送也遵守同源策略
5. 提高安全性
出于兼容的考虑,HTTP/2 延续了 HTTP/1 的“明文”特点,可以像以前一样使用明文传输数据,不强制使用加密通信,但 HTTPS 已经是大势所趋,各大主流浏览器都公开宣布只支持加密的 HTTP/2,所以,真实应用中的 HTTP/2 是还是加密的:
HTTP/2 遗留问题
HTTP/2 还会队头阻塞吗?
HTTP/2 也存在队头阻塞问题,比如丢包。
如果造成队头阻塞,问题可能比http1.1还严重,因为只有一个tcp连接,后续的传输都要等前面,http/1.1 多个tcp连接,阻塞一个,其他的还可以正常跑
HTTP/2下还会拥塞吗?
由于 TCP 连接减少而使网络拥塞状况得以改观;
慢启动时间减少,拥塞和丢包恢复速度更快。
原文