天下武功,唯'QUICK'不破,揭秘QUIC的五大特性及外网表现

HTTP从上世纪90年代诞生起,就被约定为跑在TCP协议之上的应用层协议。而后虽然HTTP协议版本从0.9到2.0,上层协议不断优化,在享受TCP带来的有序可靠的数据服务同时,却也始终绕不开TCP协议的一些弊端。此时一种基于UDP的“快”协议,不但能可靠的向上层提供数据,还能更快的把这些数据交付上去,其更革命性的给出了提升互联网交互速度的新思路。

QUIC简介

QUIC(Quick UDP Internet Connections)是谷歌提出的一种传输协议,由于其建立在UDP之上,使得相对于TCP之上的SPDY、HTTP2等其他协议,QUIC的可定制和优化的空间更大.在UDP的上层,QUIC提供了可靠、有序、安全、而且更快速的传输服务.目前,在Chrome中有85%以上关于谷歌自有业务的请求响应都是通过QUIC承载,可以说QUIC已经经受住了真实复杂外网环境的考验。

谷歌在介绍自家的QUIC协议时提到了几个关键特性:

  • 链接耗时更短
  • 拥塞控制更出色
  • 更好的多路复用
  • 前向纠错特性
  • 链接迁移特性

可以看到QUIC的这五个特性关键字都在表达:我很快。下面会分重点的提到这五个特性及安全性保证。最后用数据说话,看看在腾讯浏览服务平台下,线上QUIC业务的真实运行表现。

关于腾讯浏览服务

腾讯浏览服务(TBS,Tencent Browsing Service),依托X5内核强大的能力,整合腾讯底层浏览技术和腾讯平台资源及能力,为微信、手机QQ等合作方提供整体移动端WEB浏览服务解决方案,目前已接入超过两万款App,涵盖20个多个行业和领域。

一、建立连接

先让我们来看看对于HTTPS页面,需要花在连接阶段的耗时。

step1. TCP三次握手,花费1RTT。

step2. TLS握手。TLS完全握手耗费2RTT,简化握手需要1RTT。

TCP是面向连接的协议,通讯前需要通过握手建立连接。TLS握手的主要目的在于双方约定一个对称秘钥,用于之后的数据传输。传输秘钥十分重要,直接决定了后续传输的安全性,因此约定过程用到RSA等非对称加密来保证安全性,而且为了实现真随机设定了三次握手用来传递三个随机数,等到客户端和服务器都有这三个随机数后可以用相同的算法生成同一个对称加密秘钥。

因此HTTPS需要耗费2-3个RTT用来建立连接。而QUIC只用耗费0-1RTT的连接耗时,就能做到等同于TCP+TLS连接的效果,0RTT就等同于发给服务器的第一个包就带有请求数据,你会不会好奇怎么做到不浪费一个RTT耗时,就能建立安全的链接?

首先 UDP是不面向连接的,事先不需要握手过程就可以直接传输数据;

其次 我们之前提到过,HTTPS的TLS握手的一个主要目的在于约定一个对称秘钥,用于之后的数据传输。QUIC在这一步QUIC用了经典的秘钥加密算法(DH算法)来实现对称秘钥的交换,算法原理见下图,算法原理有兴趣的同学可以查阅资料。其巧妙之处在于,在算出对称秘钥的三个因子中,有一个因子是本地随机产生的,其不用参与网络传输,这就断绝了被第三方劫持的可能性。如果pg是大数,那么即使全部截获到了pgAB,要破解出ab也是难的。而且秘钥的随机性是服务器和客户端共同保证的,保证了真随机性。

QUIC握手过程

QUIC首次连接需要1RTT,具体过程如下:

step1:客户端发送inchoate Client Hello消息(CHLO)请求建立连接,服务器生成一组质数p以及其原根g。然后根据pg和随机生成数a算出A,将Apg放在serverConfig里面,发到Rejection消息(REJ)到客户端;

setp2:客户端随机生成一个数b,并根据serverConfig里面的pA和b就可以算出初始密钥K,并将B和用初始密钥加密的Data数据发到(full client hello消息)服务器。

step3:服务器收到客户端的数据,用客户端发来的公开数B+server config生成同样的秘钥,来解密客户端发来的数据。然后发送Server hello消息(SHLO),这时会带上自己生成的服务器公开数(服务器这是在更新自己的私钥,实际上这就是为了保证前向安全性);

step4:客户端收到这个服务器公开数后,二者便更新了秘钥,用SHA-256等算法推导出会话密钥。以后就用这个会话秘钥通讯了。

后续的连接,如果客户端本地的serverConfig没过期(包含了Apg和其他前次协商信息),直接可以计算出初始秘钥K并加密传输数据,实现0RTT握手。

二、队头阻塞&流量控制

队头阻塞问题

既然TCP握手连接代价这么大,因此为了更好的利用已经建立好的连接,减少连接耗时,http1.1协议通过长连接方式让多个同域名下的请求复用同一连接,但是必须排队使用。B请求需要等到A请求完成后进行,这样就可能导致队头阻塞现象(Head-of-line blocking),A请求不完成,后面的请求BCD都会被delay住而无法发起。

谷歌提出的SPDY协议的多路复用机制一定程度上缓解了队头阻塞现象,SPDY规定,同一链路上的请求不再依次等待,大家可以间隔进行,于是可能存在一条链路上依次有A->C->B->A的序列,你看B请求不用再等待A,C请求也不用等待B,队头阻塞不就解决了么?

其实并没有,无论HTTP2(HTTP/2 over TCP)、HTTP1.x协议还是SPDY协议都基于TCP协议,上层可以解决HOL问题,但是传输层的HOL依然存在。说起传输层TCP协议的队头阻塞,这要从TCP的流量控制策略说起了。

TCP的流量控制策略

TCP保证了数据的有序和可达性,所以原则上是数据按照序号依次发送和接收,下一个包的发送需要等到上一个包Ack到达。这样的话,在相邻两个包的发送间隙存在很长时间的空闲等待,好在TCP采用了滑动窗口机制来减少了排队等待时间,双方约定一定大小的窗口,在这个窗口内的包都可以同步发送,接收者收到一个packet时会回复Ack给发送者,发送者收到Ack后移动发送窗口,发送后续数据。

但是如果某个packet丢失或者其对应的Ack包丢失,同样会出现一方不必要的等待。如下图情况,packet 5的Ack包丢失,导致发送端无法移动发送窗口,但接收者已经在等待后面的包了。必须等到接收者超时重传这个确认包,服务器收到这个ACK包后,发送窗口才会移动,继续后面的发送行为。

同时,对于已经被接收者接收的多个packets(比如B->A->C请求的三个包),在TCP层面是无法区分这三个包对应于上层的哪三个请求的,因此如果B包出现缺失,会导致后续已经被接收的包无法被应用层读取,请求A、C的包被B包阻塞。

QUIC的流量控制策略

UDP没有流量控制机制,由于QUIC的多路复用机制(QUIC上同一域名的多条请求可以走同一个链接),其流量控制分为Stream和Connection两种级别的控制。这里Connection就是QUIC握手后建立的连接,Stream可以理解为链路上的请求。

首先,对于StreamA而言,起始的接收窗口就是其最大接收窗口(max receive window),随着接收者接收到一部分数据后,接收窗口变小。而接收到的数据中,有一部分已经读取(图中黄色部分),这部分数据的量到达一定的阈值后,就需要更新接收窗口并告知发送者。QUIC将这个阈值定义为:

update when (flow control receive offset - consumed bytes) < (max receive window / 2);

也就是当已经读取的数据大于最大接收窗口的一半时,发送WINDOW_UPDATE帧告诉发送者,接收窗口已经更新。比如告诉发送者,窗口后移了Bytes consumes字节。

而对于connection级别的流量窗口,其接收窗口大小就是各个stream接收窗口大小之和。

QUIC的流量控制机制,使得其相对于其他协议,队头阻塞问题解决得更加彻底:

1. QUIC协议中同一个Stream内,滑动窗口的移动仅取决于接收到的最大字节偏移(尽管期间可能有部分数据未被接收),而对于TCP而言,窗口滑动必须保证此前的包都有序的接收到了,其中一个packet丢失就会导致窗口等待。

2. QUIC中同一个Connection内,不同Stream互相独立,队头的Stream A被阻塞后,不妨碍StreamB、C的读取。而对于TCP而言,其不知道将不同的Stream交给上层哪一个请求,因此同一个Connection内,Stream A被阻塞后,StreamB、C必须等待。

三、拥塞控制

目前QUIC默认采用Cubic拥塞控制算法来实现拥塞控制,就这点来看和TCP采用的是一套机制(譬如我们熟知的慢开始、拥塞避免、快重传、快恢复策略),但QUIC的这套拥塞控制策略还是与TCP有一些明显的区别和改进:

- 灵活性

TCP协议内置在系统协议栈层面,你想要改变其拥塞控制策略,需要在系统层面进行修改。而QUIC基于UDP,当你想要改变拥塞控制算法,或者进行调优工作,只需要在应用层进行修改,这并不是一件困难的事情,而且对其他应用没有影响。目前谷歌提供了两套算法(Cubic和NewReno)以供选择,并提供了一套很灵活友好的接口,让你去实验新的拥塞控制算法,而且还可以为不同应用设定不同的拥塞控制策略。

- 提供更为详细的信息

QUIC提供了更加详细而准确的信息。如其严格单调递增的Packet序列 ,能够很容易的区分packet是来自重传还是首次传输,避免了重传模糊。再如QUIC携带有关收到数据包和发送ACK之间延迟的信息,可以更准确的计算RTT时间。

另外,相对于TCp的SACK(Selective Acknowledgments,用来标注哪些包已经收到了让对方更方便的选择性重传),QUIC还提供了更大范围(0-256)的NACK(Negative Acknowledgments,用来标注哪些包没有收到),来帮助发送者快速的重传丢失包。

- 尽可能避免超时重传

为了尽可能的实现快重传而不是超时重传,QUIC采用了Tail Loss Probes (TLPs)实现某些情况下的快重传机制触发。

TLP算法如下图,服务器的segments 6-10丢失,客户端在等待s6时,由于没有收到后续的序列,因此无法触发快速重传机制,时间达到probe阈值(PTO)后,TLP算法对segments10进行重传,客户端收到这个重传序列,就能触发快速重传机制。而QUIC会在PTO之前就发送两个TLPs来尽可能避免等到超时再重传。

四、QUIC的其他特性

前向纠错&重传

数据包丢失不仅导致重传耗时,还会使拥塞窗口变小,从而降低吞吐量,影响了数据传输速度。谷歌在QUIC早期采用了前向纠错码(Forward-Error Correction)来减少包丢失现象。在一个Group中带上一个额外的fec包(N+1个包),分组中任意一个包丢失,都可以用其余N个包来恢复。这种做法同时也带来了冗余,可能没10个包中就要额外传输1个冗余包,在网络状况好的时候是一种浪费,目前谷歌已经废弃了QUIC的FEC功能。

同时,对于一些非常重要的包,QUIC在发送后的短时间内如果没收到回包,便会重发请求,以确保重要的节点不被Delay。因此抓包时你可能会看到有5个CHLO包在100ms内相继被发送。

链接迁移

当客户端IP或端口发生变化时(这在移动端比较常见),TCP连接基于两端的ip:port四元组标示,因此会重新握手,而UDP不面向连接,不用握手。其上层的QUIC链路由于使用了64位Connection id作为唯一标识,四元组变化不影响链路的标示,也不用重新握手。因此网络链接状态变化时不会增加额外的握手重连耗时。


QUIC在外网环境下的表现

腾讯浏览服务上半年对部分合作方开放QUIC服务,重点接入了手机QQ会员业务和黄钻业务,这两个业务目前的日均QUIC访问量都在百万级别。我们从性能和异常监控两个维度来考察QUIC的外网表现。

一、QUIC性能表现

上图是黄钻业务下走QUIC和HTTP2的性能数据对比(取6月15-17日三天大盘上报的平均数据)。主资源拉取耗时平均减少近100ms,首屏和Pagefinish耗时减少约20%。

二、QUIC监控数据

QUIC对于其他协议有速度上的优势,而对业务来说稳定是首要的。腾讯浏览服务在QUIC场景搭建了完善的异常上报机制,对X5内核的QUIC业务进行监控。下面一起来看看QUIC的外网监控表现情况:

  • QUIC成功率监控

这一维度主要监控QUIC的连接成功率以及竞速成功率,上图为黄钻业务06月15-17号三天成功率及竞速成功率数据,目前QUIC的连接成功率保持在98%以上,QUIC的竞速成功率在70%以上。

  • QUIC失败监控

对于QUIC失败异常,X5内核提供了详细的QUIC细分错误码以分析错误原因,从上报的大盘数据来看:

- QUIC链接失败率不到2%,连接失败的情况,以QUIC连接超时为主。这种情况一般由于地区的QoS策略导致。

- QUIC失败率较高的三个省份为:贵州、广西和新疆;失败率较高的运营商为:教育网和长城宽带。


QUIC在弱网络环境下的表现

QUIC连接时的0RTT特性,以及在传输过程中对TCP协议缺陷的改进(如改进的流量控制和拥塞控制),让QUIC在弱网络下可能取得更大的速度优势。我们使用腾讯企业云的网络模拟平台模拟弱网络环境,对比QUIC和HTTP2在不同的网络丢包率下,QQ会员主页的html主资源(约60kb)加载速度。

Connect

Wait

Recv

Total

QUIC-0RTT

53.0

126.4

96.6

276.0

QUIC-1RTT

126.7

142.0

88.3

356.9

HTTP2

165.3

140.8

106.5

412.5

在WIFI网络、无丢包情况下,主资源的连接、等待、接收耗时对比如上表格所示。QUIC在连接及接收流程耗时较少,这与我们观察到的现网数据相吻合。

0%

5%

10%

20%

40%

QUIC 0RTT

276.0

291.4

366.0

527.7

1274.3

QUIC 1RTT

356.9

412.9

533.2

790.5

2670.4

HTTP2

412.5

506.9

668.5

1380.9

-

表格中列出了在不同网络丢包率下,QQ会员主资源加载耗时的对比数据。QUIC的优势随着丢包率的增大而更加明显。HTTP2在40%丢包率时开始出现页面加载不出来的现象,而QUIC还能完成请求任务。下图为随着丢包率上升,QUIC相对于HTTP的性能提升率趋势,在20%丢包率下,QUIC-1RTT下和QUIC-0RTT下请求页面主资源的耗时分别节省了约43%和62%。


加入我们,拥抱QUIC

QUIC服务目前已经在腾讯浏览服务平台落地,并且拥有完善的业务监控平台。我们同时拥有完整的端+云+监控方案,期待更多合作伙伴加入进来,享受到QUIC带来的快体验。天下武功,唯快不破,从SPDY到QUIC,网络传输中的“快”主题还在持续。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

X5内核专区

1 篇文章3 人订阅

我来说两句

5 条评论
登录 后参与评论

相关文章

来自专栏深度学习那些事儿

win10系统崩溃(unexpected_store_exception)原因以及修复办法

博主使用的windows电脑为: 机械革命(MECHREVO)深海泰坦 X6Ti 多彩版 15.6英寸游戏本i7-6700HQ 8G 128GSSD+1T G...

2764
来自专栏IT技术精选文摘

海量之道之弱联网优化

894
来自专栏惨绿少年

keepalived中的脑裂

    在高可用(HA)系统中,当联系2个节点的“心跳线”断开时,本来为一整体、动作协调的HA系统,就分裂成为2个独立的个体。由于相互失去了联系,都以为是对方出...

2430
来自专栏云上大文件传输

RaySync 传输协议的有效带宽利用率分析介绍

最近在评论区收到不少朋友反应RaySync FTP文件传输的效果挺好,谢谢大家的鼓励。也有部分熟悉技术的同学希望介绍下原理,有部分同学咨询RaySync传输协议...

4456
来自专栏码洞

全栈虚拟机GraalVM初体验

近日Oracle开源了一个实验性的产品GraalVM,官方称之为Universal GraalVM。它打通了不同语言之间的鸿沟,让我们可以进行混合式多语言编程。...

832
来自专栏张善友的专栏

开源软件的最近几个更新值得注意

1、开源版本控制系统Subversion 1.3 正式发布 :Subversion开发小组近日宣布Subversion 1.3 正式发布。SubVersion是...

1826
来自专栏企鹅号快讯

微信年度最重磅发布!小游戏突然上线,游戏行业会变天么?

为了帮助用户更便捷地使用小程序,微信在刚刚又更新了3个新功能: 1、微信在主界面新增小程序任务栏功能 2、小程序菜单升级,支持小程序间快速切换 3、开放了小游戏...

1809
来自专栏张善友的专栏

NHibernate VS IbatisNet

  NHibernate是当前最流行的Java O/R mapping框架Hibernate的移植版本,当前版本是1.0 .2。它出身于sf.net..Ibat...

1787
来自专栏FreeBuf

ATM机渗透测试的攻防实践

ATM自动柜员机为人们提供了便捷,现在大家不必去银行就能进行现金交易。用户使用它可以对资金进行敏感操作,当然其中脆弱的通信环节也引来了大量黑客的觊觎。 在过去的...

1816
来自专栏用户2442861的专栏

跟我一起学习VIM - The Life Changing Editor

前两天同事让我在小组内部分享一下VIM,于是我花了一点时间写了个简短的教程。虽然准备有限,但分享过程中大家大多带着一种惊叹的表情,原来编辑器可以这样强大,这算是...

862

扫码关注云+社区