解密HTTP/2与HTTP/3的新特性

2019 年 10 月 29 日

解密HTTP/2与HTTP/3的新特性

HTTP/2 相比于 HTTP/1.1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作。当然,兼容问题以及如何优雅降级应该是国内还不普遍使用的原因之一。虽然 HTTP/2 提高了网页的性能,但并不代表它已经完美,HTTP/3 就是为了解决 HTTP/2 存在的一些问题而被推出的。


HTTP/1.1 发明以来发生了哪些变化?


如果仔细观察打开那些最流行的网站首页所需要下载的资源的话,会发现一个非常明显的趋势。近年来,加载网站首页需要的下载的数据量在逐渐增加,并已经超过了 2100K。但在这里我们更应该关心的是:平均每个页面为了完成显示与渲染所需要下载的资源数已经超过了 100 个。


正如下图所示,从 2011 年以来, 传输数据大小与平均请求资源数量不断持续增长,并没有减缓的迹象。该图表中,绿色直线展示了传输数据大小的增长,红色直线展示了平均请求资源数量的增长。



HTTP/1.1 自从 1997 年发布以来,我们已经使用 HTTP/1.x 相当长一段时间了,但是随着近十年互联网的爆炸式发展,从当初网页内容以文本为主, 到现在以富媒体(如图片、声音、视频)为主, 而且对页面内容实时性要求高的应用越来越多 (如聊天、视频直播), 于是当时协议规定的某些特性,已经无法满足现代网络的需求了。


HTTP/1.1 的缺陷


1. 高延迟 – 带来页面加载速度的降低


虽然近几年来网络带宽增长非常快,然而我们却并没有看到网络延迟有对应程度的降低。网络延迟问题主要由于队头阻塞 (Head-Of-Line Blocking)产生,导致带宽无法被充分利用



队头阻塞是指,当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。针对队头阻塞, 人们尝试过以下办法来解决:


  • 将同一页面的资源分散到不同域名下,提升连接上限。Chrome 有个机制,对于同一个域名,默认允许同时建立 6 个 TCP 持久连接。使用持久连接时,虽然能共用一个 TCP 管道,但是在一个管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。另外,如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。

  • Spriting 合并多张小图为一张大图, 再用 JavaScript 或者 CSS 将小图重新“切割”出来的技术。

  • 内联 (Inlining) 是另一种防止发送很多小图请求的技巧,将图片的原始数据嵌入在 CSS 文件里面的 URL 里,减少网络请求次数。


.icon1 {    background: url(data:image/png;base64,<data>) no-repeat;  }.icon2 {    background: url(data:image/png;base64,<data>) no-repeat;  }
复制代码


  • 拼接 (Concatenation) 将多个体积较小的 JavaScript 使用 webpack 等工具打包成 1 个体积更大的 JavaScript 文件, 但如果其中 1 个文件改动,会导致大量数据被重新下载多个文件。


2. 无状态特性 – 带来巨大的 HTTP 头部


由于报文 Header 一般会携带"User Agent" “Cookie”“Accept”"Server"等许多固定的头字段(如下图),多达几百字节甚至上千字节,但 Body 却经常只有几十字节(比如 GET 请求、 204/301/304 响应),成了不折不扣的“大头儿子”。Header 里携带的内容过大,在一定程度上增加了传输成本。更要命的是,成千上万的请求响应报文里有很多字段值都是重复的,非常浪费。



3. 明文传输 – 带来不安全性


HTTP/1.1 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。


你有没有听说过"免费 WiFi 陷阱”之类的新闻呢?黑客就是利用了 HTTP 明文传输的缺点,在公共场所架设一个 WiFi 热点开始“钓鱼”,诱骗网民上网。一旦你连上了这个 WiFi 热点,所有的流量都会被截获保存,里面如果有银行卡号、网站密码等敏感信息的话那就危险了,黑客拿到了这些数据就可以冒充你,为所欲为。


4. 不支持服务器推送消息


SPDY 协议与 HTTP/2 简介


1.SPDY 协议


上面我们提到, 由于 HTTP/1.x 的缺陷,我们会引入雪碧图、将小图内联、使用多个域名等方式来提高性能,不过这些优化都绕开了协议。直到 2009 年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。谷歌推出 SPDY,才算是正式改造 HTTP 协议本身。降低延迟,压缩 header 等等,SPDY 的实践证明了这些优化的效果,也最终带来 HTTP/2 的诞生。



HTTP/1.1 有两个主要的缺点:安全不足和性能不高。由于背负着 HTTP/1.x 庞大的历史包袱, 所以协议的修改, 兼容性是首要考虑的目标,否则就会破坏互联网上无数现有的资产。如上图所示, SPDY 位于 HTTP 之下,TCP 和 SSL 之上,这样可以轻松兼容老版本的 HTTP 协议 (将 HTTP1.x 的内容封装成一种新的 frame 格式),同时可以使用已有的 SSL 功能。


SPDY 协议在 Chrome 浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 中得到继承。


2.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 由两个规范(Specification)组成:


  1. Hypertext Transfer Protocol version 2 - RFC7540

  2. HPACK - Header Compression for HTTP/2 - RFC7541


HTTP/2 新特性


1. 二进制传输


HTTP/2 传输数据量的大幅减少, 主要有两个原因: 以二进制方式传输和 Header 压缩。我们先来介绍二进制传输,HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 里纯文本形式的报文 ,二进制协议解析起来更高效。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码


它把 TCP 协议的部分特性挪到了应用层,把原来的"Header+Body"的消息"打散"为数个小片的二进制"帧"(Frame), 用"HEADERS"帧存放头数据、"DATA"帧存放实体数据。HTTP/2 数据分帧后,“Header+Body"的报文结构就完全消失了,协议看到的只是一个个"碎片”。



HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装


2.Header 压缩


HTTP/2 并没有使用传统的压缩算法,而是开发了专门的"HPACK”算法,在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,还采用哈夫曼编码来压缩整数和字符串,可以达到 50%~90% 的高压缩率。


具体来说:


  • 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键 - 值对,对于相同的数据,不再通过每次请求和响应发送。

  • 首部表在 HTTP/2 的连接存续期内始终存在,由客户端和服务器共同渐进地更新 。

  • 每个新的首部键 - 值对要么被追加到当前表的末尾,要么替换表中之前的值。


例如下图中的两个请求, 请求一发送了所有的头部字段,第二个请求则只需要发送差异数据,这样可以减少冗余数据,降低开销 。



3. 多路复用


在 HTTP/2 中引入了多路复用的技术。多路复用很好地解决了浏览器限制同一个域名下请求数量的问题,同时也更容易实现全速传输,毕竟新开一个 TCP 连接都需要慢慢提升传输速度。


大家可以通过该链接直观感受下 HTTP/2 比 HTTP/1 到底快了多少: https://http2.akamai.com/demo



在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2 中:


  • 同域名下所有通信都在单个连接上完成。

  • 单个连接可以承载任意数量的双向数据流。

  • 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。


这一特性使性能有了极大提升:


  • 同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应, 这样整个页面资源的下载过程只需要一次慢启动,同时也避免了多个 TCP 连接竞争带宽所带来的问题。

  • 并行交错地发送多个请求 / 响应,请求 / 响应之间互不影响。

  • 在 HTTP/2 中,每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。



如上图所示,多路复用的技术只通过一个 TCP 连接就可以传输所有的请求数据。


4.Server Push


HTTP2 还在一定程度上改变了传统的“请求 - 应答”工作模式,服务器不再完全被动地响应请求,也可以新建“流”主动向客户端发送消息。比如,在浏览器刚请求 HTML 的时候就提前把可能会用到的 JS、CSS 文件发给客户端,减少等待的延迟,这被称为"服务器推送"( Server Push,也叫 Cache push)。


如下图所示,服务端主动把 JS 和 CSS 文件推送给客户端,而不需要客户端解析 HTML 时再发送这些请求。



另外需要补充的是,服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送 RST_STREAM 帧来拒收。主动推送也遵守同源策略。换句话说,服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。


5. 提高安全性


出于兼容的考虑,HTTP/2 延续了 HTTP/1 的“明文”特点,可以像以前一样使用明文传输数据,不强制使用加密通信,不过格式还是二进制,只是不需要解密。


但由于 HTTPS 已经是大势所趋,而且主流的浏览器 Chrome、Firefox 等都公开宣布只支持加密的 HTTP/2,所以“事实上”的 HTTP/2 是加密的。也就是说,互联网上通常所能见到的 HTTP/2 都是使用"https”协议名,跑在 TLS 上面。HTTP/2 协议定义了两个字符串标识符:“h2"表示加密的 HTTP/2,“h2c”表示明文的 HTTP/2。



HTTP/3 新特性


1.HTTP/2 的缺点


虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,主要是底层支撑的 TCP 协议造成的。HTTP/2 的缺点主要有以下几点:


  • TCP 和 TCP+TLS 建立连接的延时


HTTP/2 是使用 TCP 协议来传输的。如果使用 HTTPS 的话,还需要使用 TLS 协议进行安全传输,而使用 TLS 也需要一个握手过程,这样就需要有两个握手延迟过程


①在建立 TCP 连接的时候,需要和服务器进行三次握手来确认连接成功,也就是说需要在消耗完 1.5 个 RTT 之后才能进行数据传输。


②进行 TLS 连接,TLS 有两个版本——TLS1.2 和 TLS1.3,每个版本建立连接所花的时间不同,大致是需要 1~2 个 RTT。


总之,在传输数据之前,我们需要花掉 3~4 个 RTT。


  • TCP 的队头阻塞并没有彻底解决


上文我们提到在 HTTP/2 中,多个请求是跑在一个 TCP 管道中的。但当出现了丢包时,HTTP/2 的表现反倒不如 HTTP/1 了。因为 TCP 为了保证可靠传输,有个特别的“丢包重传”机制,丢失的包必须要等待重新传输确认,HTTP/2 出现丢包时,整个 TCP 都要开始等待重传,那么就会阻塞该 TCP 连接中的所有请求(如下图)。而对于 HTTP/1.1 来说,可以开启多个 TCP 连接,出现这种情况反倒只会影响其中一个连接,剩余的 TCP 连接还可以正常传输数据。



读到这里,可能就会有人考虑为什么不直接去修改 TCP 协议?其实这已经是一件不可能完成的任务了。因为 TCP 存在的时间实在太长,已经充斥在各种设备中,并且这个协议是由操作系统实现的,更新起来不大现实。


2.HTTP/3 简介


Google 在推 SPDY 的时候就已经意识到了这些问题,于是就另起炉灶搞了一个基于 UDP 协议的“QUIC”协议,让 HTTP 跑在 QUIC 上而不是 TCP 上。而这个“HTTP over QUIC”就是 HTTP 协议的下一个大版本,HTTP/3。它在 HTTP/2 的基础上又实现了质的飞跃,真正“完美”地解决了“队头阻塞”问题。



QUIC 虽然基于 UDP,但是在原本的基础上新增了很多功能,接下来我们重点介绍几个 QUIC 新功能。不过 HTTP/3 目前还处于草案阶段,正式发布前可能会有变动,所以本文尽量不涉及那些不稳定的细节。


3.QUIC 新功能


上面我们提到 QUIC 基于 UDP,而 UDP 是“无连接”的,根本就不需要“握手”和“挥手”,所以就比 TCP 来得快。此外,QUIC 也实现了可靠传输,保证数据一定能够抵达目的地。它还引入了类似 HTTP/2 的“流”和“多路复用”,单个“流"是有序的,可能会因为丢包而阻塞,但其他“流”不会受到影响。具体来说,QUIC 协议有以下特点:


  • 实现了类似 TCP 的流量控制、传输可靠性的功能。


虽然 UDP 不提供可靠性的传输,但 QUIC 在 UDP 的基础之上增加了一层来保证数据可靠性传输。它提供了数据包重传、拥塞控制以及其他一些 TCP 中存在的特性。


  • 实现了快速握手功能。


由于 QUIC 是基于 UDP 的,所以 QUIC 可以实现使用 0-RTT 或者 1-RTT 来建立连接,这意味着 QUIC 可以用最快的速度来发送和接收数据,这样可以大大提升首次打开页面的速度。0RTT 建连可以说是 QUIC 相比 HTTP2 最大的性能优势


  • 集成了 TLS 加密功能。


目前 QUIC 使用的是 TLS1.3,相较于早期版本 TLS1.3 有更多的优点,其中最重要的一点是减少了握手所花费的 RTT 个数。


  • 多路复用,彻底解决 TCP 中队头阻塞的问题。


和 TCP 不同,QUIC 实现了在同一物理连接上可以有多个独立的逻辑数据流(如下图)。实现了数据流的单独传输,就解决了 TCP 中队头阻塞的问题。



总结


  • HTTP/1.1 有两个主要的缺点:安全不足和性能不高。

  • HTTP/2 完全兼容 HTTP/1,是“更安全的 HTTP、更快的 HTTPS",头部压缩、多路复用等技术可以充分利用带宽,降低延迟,从而大幅度提高上网体验。

  • QUIC 基于 UDP 实现,是 HTTP/3 中的底层支撑协议。该协议基于 UDP,又汲取了 TCP 中的精华,实现了既快又可靠的协议。


本文转载自微信公众号:前端工匠


2019 年 10 月 29 日 08:104508

评论 1 条评论

发布
用户头像
然而现在大多数还在用这http1.1
2019 年 11 月 03 日 16:40
回复
没有更多评论了
发现更多内容

Week_11 总结

golangboy

极客大学架构师训练营

ShardingSphere RAW JDBC 分布式事务 Narayana XA 代码示例

Java 数据库 分布式事务 ShardingSphere

架构师训练营第 11 周学习笔记

郎哲158

Spring 源码学习 08:register 注册配置类

程序员小航

Java spring 源码 源码阅读

第 07 周 性能压测(响应时间和吞吐量变化)

Airship

极客大学架构师训练营

8张图带你了解大型应用架构演进历程

Silently9527

架构 互联网架构设计

架构师训练营 2 期 Week07 总结

Calvin

架构师训练营第 1 期 - 第 10 周 - 命题作业

wgl

Week_11 作业

golangboy

极客大学架构师训练营

从一次不佳的小组讨论展开

sherlockq

CSS flex 排版与动画 — 重学 CSS

三钻

CSS 排版 前端进阶训练营 Flex

week7-性能优化

KMP —— 字符串分析算法

三钻

算法 前端 前端进阶训练营 KMP

week02

ルンルン

第11周作业

paul

话题讨论 | 未来十年,你认为哪门语言将要脱颖而出

soolaugust

话题讨论

架构训练营第七周作业

一期一会

性能测试 go语言

训练营 - 第11周

袭望

与前端训练营的日子 --Week06

SamGe

学习

密码学,心底的凉暖

范学雷

密码学

【架构师训练营 1 期】第十一周学习总结

诺乐

话题讨论 | 2021要来了,你对未来的一年有什么期待

soolaugust

话题讨论

腾讯牵头零信任产业标准工作组正式发布零信任联盟标准

Geek_459987

腾讯iOA与绿盟、天融信完成产品互认证,助力零信任市场协同发展

Geek_459987

第十一周 学习总结

熊桂平

极客大学架构师训练营

话题讨论 | 2020就要结束了,你最想对自己说的是什么

soolaugust

话题讨论

架构师训练营 11 周作业

郎哲158

week7-作业二:根据当周学习情况,完成一篇学习总结

第十一周 作业

熊桂平

极客大学架构师训练营

【架构师训练营 1 期】第十一周作业

诺乐

话题讨论 | 遇到的印象最深的开源项目

soolaugust

话题讨论

解密HTTP/2与HTTP/3的新特性-InfoQ