前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WEB加速,协议先行 ( 上)

WEB加速,协议先行 ( 上)

原创
作者头像
腾讯技术工程官方号
修改2017-07-14 17:41:10
1.9K0
修改2017-07-14 17:41:10
举报
文章被收录于专栏:腾讯技术工程官方号的专栏

导语:2017年7月7日-8日,ArchSummit全球架构师峰会在深圳召开,腾讯技术工程事业群基础架构部高级工程师lancelot作为演讲嘉宾,分享了STGW及腾讯云CLB在WEB协议优化过程中的实践经验,并对WEB协议的未来进行了探讨分析,以下为现场演讲内容的整理稿。

[1499830671724_6077_1499830672164.jpg]
[1499830671724_6077_1499830672164.jpg]

演讲主题:WEB加速,协议先行

演讲嘉宾:TEG基础架构部高级工程师 lancelot

我们平时使用Web应用的时候,一定会经常遇到非常多的访问问题,比如“无法接入网络”,比如“网页一直在加载”,又比如“视频卡顿”。那导致这些问题的背后原因有哪些呢?下图简单罗列了一下,主要有如下几类:

[1499830704863_8585_1499830705041.jpg]
[1499830704863_8585_1499830705041.jpg]

其中页面大小主要是指页面的体积,页面的元素主要是指页面元素类型以及数量,通常来讲,一个页面体积越大,页面元素越多,动态交互的元素越多,那这个页面的性能相应就会低一点。页面相关的性能问题也是前端工作优化的主战场。

[1499830722133_4603_1499830722327.jpg]
[1499830722133_4603_1499830722327.jpg]

那WEB请求主要会涉及到哪些网络协议?我们以现在逐渐流行的互联网下一代协议HTTP2为例,详细介绍一下一条HTTP2请求需要经过的协议栈。上图左边是客户端,右边是数据中心,也就是服务端。

客户端首先需要经过HTTP1.1协议,为什么是HTTP1.1协议?这是因为HTTP2虽然是一个全新的协议,但是它沿用的大部分语义还是HTTP1.1。比如常用的Get 请求,Post请求,都是沿用的HTTP1.1的语义。对于js或者页面来讲,和HTTP1.1没有变化。HTTP1.1然后就到了HTTP2协议,HTTP1.1的语义需要经过HTTP2 frame的封装,比如Get请求会经过HEADERs frame封装,Post请求的body需要经过HTTP2 data frame的封装。再然后就来到TLS协议,传输加密层,这里为什么会有加密?事实上HTTP2 RFC7540规定,HTTP2有两种实现,一种是H2,需要强制加密;还有一种H2C,这里的C是指clear,就是明文,不需要加密的意思。虽然协议规定有两种实现,但是现在所有的主流实现,包括所有的客户端,chrome,firefox,ie,safari和所有的操作系统,都是强制使用的TLS加密。加密层再往下就来到了大家用的很多的TCP层。TCP接着往下就到了IP网络层,以及以太网链路层再经过运营商网络物理层等等到达服务端,然后经过相同的协议栈进行处理,就不多做介绍了。

那这么多协议,我们需要关注哪些?图中白色虚线往上的部分就是我们需要关注的部分,因为这部分才是客户端能够控制,能够施加影响的协议。至于网络层及链路层等更低层的协议,客户端是很难或者无法控制的。明确了我们需要关注的协议,那这些协议分别存在哪些问题?

[1499830744947_7148_1499830745202.png]
[1499830744947_7148_1499830745202.png]

还是从历史最悠久使用最广泛的HTTP1.1协议说起。HTTP1.1协议最大的性能问题就是“单链接串行”。即在一个TCP链接上如果有多个请求,请求和请求之间必须按照次序串行发送。如图中右边所示。CSS和JS及JPG请求需要依次发送。“单链接串行”大家也都比较清楚了,这里再看下头部未压缩,会导致的两个问题:

1.数据冗余,重复传输,浪费带宽。每次请求的Host,Cookie,UA等字段都是一模一样的,没啥意义。

2.影响访问速度。特别是由于我们运营商网络上下行带宽严重不对称,上行带宽往往是下行带宽的10分之1甚至不到,比如通常说带宽1M或者10M,上行带宽往往只有100K甚至几十K,我们统计的头部平均大小是1500个字节,有时候头部变大就很可能在带宽层面影响访问性能。

[1499830766810_1010_1499830767005.jpg]
[1499830766810_1010_1499830767005.jpg]

概括来讲,HTTP1.1的优化方向主要是两点:

1.增加并发连接数量。不管是单域名多TCP连接,还是域名分片,本质上都是希望通过建立多个并发连接,来提升并发请求效率。其实HTTP1.1尝试过在单链接上并发请求来提升性能,比如pipelining,但由于存在队头阻塞,最后还是以失败告终。

2.减少请求数量。不管是CSS雪碧图,还是data uri,图片内联等,都是希望将多个响应包装到一个响应里返回。缓存也是希望在本地就能获取到内容,不需要发出请求。

HTTP1.1的这些优化手段在HTTP1.1时代其实也取得了比较好的效果,也是被实践证明的行之有效的方案,是在性能方面有很大的提升。

[1499830786142_1604_1499830786341.jpg]
[1499830786142_1604_1499830786341.jpg]

首先看一下背景,全站HTTPS趋势是越来越明显,不管是国内的BAT还是国外的FLAG,都已经支持了全站HTTPS。

HTTP2呢,2015年5月正式发布,目前也有13.7%的网站支持了HTTP2。HTTPS性能上一个很大的特点或者说缺点就是连接成本高,而HTTP1.1的一个优化方向就是增加并发连接数量,如果单个连接成本变高了,并发连接的成本相应也会提高,所以还是依靠增加并发连接数量来提升性能,反而会起到副作用。

HTTP2最强大的特性就是支持多路复用,能够将多个请求在一个链接上同时发送,实现并发请求。这样HTTP1.1另外一个优化方向,减少请求数量,也就没有太大意义了,因为减少请求数量,特别是内联,可能会有降低缓存命中率,而且也会增加服务端的开发和维护成本。

所以从这个层面讲,HTTP1.1的优化策略逐渐失效了。那刚才提到高连接成本,HTTPS为什么会有这么高的连接成本?

[1499830803229_6018_1499830803497.png]
[1499830803229_6018_1499830803497.png]

左边是一次HTTP1.1的请求过程,非常简单,只需要通过三次握手建立TCP连接,然后就可以在这个TCP连接上发送HTTP1.1数据了。总共只需要2个RTT就能完成一次交互。右边是HTTPS的一次请求过程,非常复杂。简单说一下过程。

1.首先同样需要建立TCP连接。

2.然后开始发送HTTP1.1数据,这里为什么会是HTTP1.1的数据呢?因为如果是用户主动输入URL的情况下,绝大部分用户不会主动输入HTTPS,比如他访问腾讯网,他可能会输入qq.com或者www.qq.com 或者 http://www.qq.com ,但是他很少会输入 https://www.qq.com ,这样我们就只能通过返回302强制用户使用HTTPS。

  1. HTTPS使用的是443端口,HTTP使用的是80端口,不同的端口必须要建立不同的TCP连接。这样又需要三次握手来建立TLS的TCP连接。

4.然后就可以在这个TCP连接上进行TLS握手了,首先完全握手阶段一,主要是协商协议版本,密码套件,返回证书。

5.客户端在获取到证书后,校验完证书的签名和时间都没有问题后,还是有可能要检查这个证书的状态,因为我们有可能主动撤销了这个证书,也有可能是CA本身数据库出了安全问题。所以又需要解析这个CA OCSP站点的域名。

6.然后向这个CA站点的IP发起三次握手建立TCP连接。

7.建立好TCP连接后,开始请求OCSP的内容,也是通过HTTP协议完成的。

8.OCSP校验通过后,开始进行TLS完全握手阶段二,这个阶段主要是完成非对称密钥交换计算协商出对称密钥。

9.至此,TLS握手完全结束,开始进行HTTP应用层的加密内容传输。

由些可见,一次HTTPS的请求有可能需要9个RTT,相比HTTP1.1多出了7个RTT。

[1499830831412_6452_1499830831613.jpg]
[1499830831412_6452_1499830831613.jpg]

7个RTT是什么概念呢?最好的WIFI环境下,我们统计的平均RTT是70ms,7个RTT就是490ms,4G是100ms,3G是200ms。这还仅仅是一次请求的耗时,我们一个页面往往有数十个请求,请求和请求之间还有可能依赖,有可能阻塞,这样下来,一个HTTPS页面增加几秒钟也是非常正常的现象。

如上描述的还只是HTTPS的的网络耗时,也就是协议的规定所必须要进行的网络交互。还有一部分耗时是计算耗时,比如客户端需要校验证书,计算密钥,服务端也需要非对称密钥计算出对称密钥,还需要对内容进行对称加解密。特别是移动端的CPU相对要弱,所以计算层面的耗时多出几百毫秒也是比较正常的。

从上述原理分析,未经优化的HTTPS的速度要明显慢于HTTP。那HTTPS就等于HTTP+SLOW吗?如果是,那除了上述网络协议的原理分析,还存在其他的性能瓶颈吗?接下去我们分别从线下测试及线下业务数据的角度来进一步分析。

[1499830849786_33_1499830849990.jpg]
[1499830849786_33_1499830849990.jpg]

线下模拟测试主要是关注移动端。移动端手机有两个问题:

1.手机屏幕比较小,不方便页面性能分析和数据的查看。

2.不方便执行我们自动控制脚本和数据分析脚本。

于是我们使用USB数据线将手机和PC连接起来,再通过chrome remote debug协议来控制手机不断的重复地访问我们所构造的不同的测试页面。所以一定要使用自动化的脚本去访问,这样才会非常方便地生产大量数据,包括各种应用场景。见过很多同事,拿着自己人工生成的几十条数据就误认为是结论,这样的数据几乎是没有意义的。

另外就是要考虑消除误差,一定要注意数据的周期性的同比,环比,数据量一般超过10000条才有一定的可信度。还有一个很大的误差是WIFI网络非常不稳定,即使在我们办公室里面,比如腾讯大厦或者朗科大厦,WIFI也很容易丢包,延时抖动等。为了减少WIFI的影响,我们同样的是使用USB线将手机和电脑连接,使得手机直接通过有线网络去请求页面,因为有线网络相对要稳定很多,能很大程度地减少WIFI的影响。

还有一个工具就是traffic control,因为我们真实的用户网络环境是千差万别的,有2G,3G,4G,WIFI,有不同的RTT,不同的带宽,不同的丢包率。在办公室是无法获取这么多真实的网络条件的,只能通过模拟,那 linux traffic control就能很好的模拟这些场景。

上述主要是介绍了一下我们线下模拟测试的经验。但是线下测试的数据毕竟不能代表线上真实用户的体验,所以我们还需要对线上真实业务进行数据监控和分析。

[1499830871728_4431_1499830872009.png]
[1499830871728_4431_1499830872009.png]

线上速度监控的方案其实有非常多,我相信只要关注过速度或者前端性能的朋友都有一些比较成熟的做法,我就不多做介绍了。这里我想重点分享的是我们基于服务端进行数据采集的方案。为什么要基于服务端采集数据呢?主要是有两大优势 :

1.服务端能采集到客户端采集不到的数据。比如业务处理的整体时间,又比如跟协议相关的信息,包括是否TCP连接复用,TCP的RTT,是否TLS Session复用,TLS协议版本,密码套件,TLS非对称密钥交换计算的时间,握手时间,HTTP2的头部压缩比等。

2.开发成本低。因为有一些数据客户端如果有网络读写能力,也能获取到一些底层信息,但是客户端的操作系统种类多,有iOS,android,windows等,不同的系统,不同的版本,开发方案肯定是不同的。但是服务端一次开发就可以适配所有客户端,因为服务端将统计的数据,放到cookie里返回给了客户端,客户端只需要通过JS就能获取到cookie里的信息,然后JS又将自己采集到的和页面相关信息汇聚,最后统一上报到报表分析平台。

那采集了这么多协议相关的信息,拿到了这么多数据,我们该如何分析?

[1499830899364_2586_1499830899604.jpg]
[1499830899364_2586_1499830899604.jpg]

上表只是截取了我们很少的几个维度,其中第一列是我们的统计维度,比如tcp_reuse表示TCP连接复用,TLSv1.2表示TLS协议版本是1.2,ecdhe_rsa_aes128

_gcm_sha256表示密码套件等。

第一行中的其他数据表示我们的监控指标,比如start_load表示开始加载的时间,active表示页面可以活动的时间,req_time表示业务处理的时间等。上述这些单一维度又可以进行多维度的整合,比如这行黄色的文字所示“腾讯X5内核浏览器在4G网络下使用HTTP2并且是TLS1.2协议并且使用ECDHE并且没有复用tls session的首屏时间是多少?”我们清晰地看到它使用TLS1.1,1.0,以及其他密码套件的一些性能数据,为什么快,为什么慢,通过这样的多维度对比,一目了然。也就是说我们收集了这么多的数据,并不是用来好看的,也不是仅仅用来做报表的,最终是为了找到其中的性能瓶颈,从而为我们的速度优化寻找方向。那我们主要有哪些方向?

这里主要从非前端的角度讲述一下我们的优化方向,主要是这三大块:协议,资源, 用户行为。首先我们来看一下协议,这次我们从最底层的TCP协议说起。

[1499830919555_3862_1499830919819.png]
[1499830919555_3862_1499830919819.png]

TCP协议在性能方面最显而易见的问题就是它需要三次握手才能建立一个连接,才能发送数据,浪费了一个RTT。那TCP fast open的思路就是在SYN包发出的同时将应用层数据一起发出来,减少三次握手对延时的影响。

TFO的大概流程是这样的,首先也需要三次握手才能建立连接,所不同的是,服务端返回syn+ack的时候还会返回一个cookie。这样在下一次建立连接时,客户端就会发出syn包的同时,将cookie 和应用层数据一起发出来,减少了这个RTT的浪费。

TFO的优化效果其实也很明显,我们统计80分位的数据提升了100毫秒。它的缺点也比较明显,就是需要客户端的操作系统支持,比如iOS9+以及linux kervel3.7+才支持TFO,windows都还不支持。

TCP另外一个优化就是增加初始拥塞窗口,由3个增加到10个。这个其实也是Google很早就提出的一个方案,也被标准内核采纳了,所以我就不多做介绍了。包括Google最近提出的BBR算法,对于长肥管道也有一定的效果。

总的来说,在TCP层面进行优化的空间不大,成本很高。因为它需要操作系统,需要内核的支持。如果仅仅是服务端开发倒还好,关键是需要用户,甚至需要广大的网络中间设备的系统和协议栈支持,这样就会导致部署阻力非常大。

接下篇《 WEB加速,协议先行 ( 下)

注:本篇内容来自“腾讯技术工程官方号”,公众号ID:tegwzx

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档