得物技术网络优化-CDN资源请求优化实践

2,024 阅读15分钟

1.前言

为用户提供更加流畅的App使用体验是我们的目标。作为电商类App,社区+交易相关业务强依赖图片、视频、文件等静态资源。由于这些静态资源部署在CDN上,因此本文统称为“CDN资源”。

虽然部署到CDN服务后提升了CDN资源的请求性能,但只能算是初始阶段,App端依然存在资源加载慢、卡顿等体验问题,离预期还有一定距离,需要进一步优化。因此,2021年下半年我们对CDN资源的网络请求性能进行了重点优化,取得了明显的效果,本文在此进行一个阶段性总结。

2.内容介绍

本文主要介绍得物 CDN 资源请求实现平均耗时 iOS 端降低18%+, Android 端降低10%+ 的优化思路及优化实践经验。整体按监控数据分析,优化方向调研,优化方案设计,推进优化落地,优化效果反馈的流程执行,达到逐步优化的效果。本文主要讲4个优化方向,包括:CDN部署调整,TLS1.3升级,OCSP Stapling开启,Http2.0升级。下面就来详细介绍下每个优化方向具体如何确定的,优化的方案,以及优化效果。

3.优化案例

3.1 CDN部署调整

3.1.1 什么是CDN服务?

可能有的同学对CDN还不太熟悉,我们先简单介绍下CDN的概念及原理。CDN(Content Delivery Network)指内容分发网络,由分布在不同地区的边缘服务器节点组成的分布式网络,负责缓存源站静态资源并就近分发给用户,达到降低静态资源请求耗时,降低源站服务器压力的目的。

CDN服务的优势:就近接入,资源缓存,降低回源,智能选路,高效传输,智能压缩,安全,高性能等特性(摘自阿里云CDN文档介绍)。简单来说就是就近接入,资源缓存,高效回源这3大特性。

静态资源部署到CDN服务后,访问链路从请求源站变为就近接入CDN边缘节点,大大缩短了网络访问链路,降低了CDN资源的请求耗时。如广东用户原来请求CDN资源需要访问杭州源站,现在可以直接访问广东省内的CDN边缘节点获取CDN资源。

CDN边缘节点如果有当前请求的CDN资源缓存,则直接将缓存返回给客户端;如果没有缓存,则通过CDN服务系统内部策略实现高效回源,资源获取后返回到CDN边缘节点并缓存,再返回给客户端。

下图可以直观的展现出部署到CDN服务前后用户请求静态资源的变化

(注:图片来自网络)

3.1.2 从地域维度分析CDN资源请求耗时监控数据

了解了CDN的原理后,我们就知道,CDN服务效果是和地域强相关的。对不同地区的用户来说,该地区是否部署了CDN服务器节点,部署了多少台CDN服务器节点来承载流量直接影响着该地区用户CDN资源请求的耗时长短。因此,考虑先从CDN按地区部署的角度对CDN资源请求监控数据进行分析。

我们重点分析平均耗时大于等于500ms的省份,其中广东省作为一线省份,网络基础设施应该比较完善,为什么平均耗时在500ms以上?

初步推测:可能是CDN服务器节点部署不合理,未在广东省部署或在广东省部署较少,广东用户无法就近接入CDN服务,跨域访问导致CDN资源请求耗时较长。

3.1.3 阿里云CDN部署情况调研

我们将这个推测反馈给阿里云客服,让其核实服务于得物的CDN边缘节点在各省份的分布情况以及广东省CDN边缘节点的部署情况。

排查结果:未部署广东、北京,并且湖南、四川、江苏、吉林部署节点偏少。

调研结论:这些地区的用户存在跨域请求CDN资源的问题,导致请求平均耗时较长。

3.1.4 CDN部署优化方案

问题原因定位后,解决方案比较简单,合理调整CDN边缘节点部署:

1.新增广东、北京本省节点;

2.新增湖南、四川、吉林、江苏本省节点,替换外省冗余节点。

3.1.5 CDN 部署优化效果

CDN域名cdn.poizon.com 优化前后数据:

平均耗时

  1. iOS:429ms -> 331ms,降低98ms

  1. Android:386ms -> 348ms,降低38ms

3.2 TLS1.3升级

一次完整的Https网络请求包含7个阶段:请求准备、 DNS 解析、TCP建连、SSL握手、Request阶段、服务端处理阶段、Response阶段

为了更详细的分析得物CDN资源请求性能数据,我们在App端将每次请求各阶段的耗时进行了单独埋点采样上报,CDN网络监控平台提供了按网络请求阶段聚合量化的性能指标。因此,对网络请求各阶段的监控数据进行分析,看是否有可优化的阶段。

3.2.1 从 网络 请求阶段维度分析 CDN 资源请求耗时 监控 数据

网络请求阶段耗时详情如下图

从图中可以看到,SSL阶段平均耗时127ms+,占累积耗时25%以上。SSL阶段耗时对整体耗时影响较大,因此考虑对SSL阶段性能优化。

对于Https请求,SSL阶段主要是进行密钥协商,保证数据加密传输的。目前得物CDN资源请求使用的是TLS1.2协议,而最新的TLS1.3协议也已经比较成熟,是否可以通过升级TLS1.3协议来实现对SSL阶段性能优化的目的呢?

3.2.2 TLS1.3协议调研

TLS1.3协议有哪些优势?与TLS1.2协议的区别?

TLS(Transport Layer Security Protocol)是传输层安全协议,TLS1.2协议2008年发布,TLS1.3协议2018年发布。

TLS1.2协议目前使用最广泛,从2008年发布到现在13年多的时间里被发现了一些缺点:

1.性能较差:握手过程需要2个RTT;

2.安全性较低:使用了不安全的加密算法,如SHA1,RC4,CBC等加密算法。

TLS1.3协议则是基于TLS1.2进行了大量优化,包括:

1.性能优化:引入了新的密钥协商机制PSK,握手过程仅需1RTT,比TLS1.2协议降低50%+;

2.安全性提高:废弃了TLS1.2协议中众多不安全及老旧的加密算法,不再使用DSA证书,ServerHello之后的握手信息都进行了加密等。

友商使用TLS1.3的情况调研

调研友商的CDN资源请求TLS协议,友商App使用的TLS1.3协议,验证了TLS1.3协议的可行性。

通过Chrome浏览器加载友商的图片,在DevTools窗口的Security面板可以看到使用的是TLS1.3协议。

客户端双端TLS1.3兼容性调研

双端主流机型已支持TLS1.3,且不支持TLS1.3的机型阿里云CDN服务也做了兼容,会根据客户端使用的TLS协议版本自动匹配使用对应的TLS协议。

线下测试:使用Debug包在线下环境分别使用TLS1.3协议与TLS1.2协议请求CDN资源,均请求正常。

3.2.3 TLS1.3升级优化方案

TLS1.3相比TLS1.2可以将SSL阶段耗时降低50%+,因此采用升级TLS1.3协议的方式实现对CDN资源请求SSL阶段耗时的优化,详细优化方案可以参考之前发布的一篇文章《得物网络优化-TLS1.3升级最佳实践》mp.weixin.qq.com/s/C0dfQ52bW…

3.2.4 TLS1.3升级优化效果

CDN cdn.poizon.com升级TLS1.3后,双端平均耗时、TLS耗时均有明显降低,优化前后数据:

平均耗时

  1. iOS:281ms -> 237ms,降低44ms

  2. Android:307ms -> 269ms,降低38ms

SSL阶段耗时

  1. iOS:210ms -> 137ms,降低73ms

  2. Android:83ms -> 71ms,降低12ms

3.3 OCSP Stapling开启

TLS1.3升级后,CDN资源请求性能提升了不少,但双端SSL阶段耗时依然有优化空间,因此继续调研SSL阶段的优化方案。通过调研后发现SSL阶段证书交换需要使用OCSP协议验证SSL证书的有效性。那什么是OCSP协议呢?OCSP协议是否会对SSL阶段性能造成影响?

3.3.1 什么是OCSP协议?

OCSP(Online Certificate Status Protocol)是在线证书状态协议,用于验证SSL证书的有效性,确保SSL证书未被吊销或过期。CA服务器提供了在线查询证书状态的接口,客户端可以在SSL阶段实时向CA服务器发起一次证书状态查询请求,CA服务器会回复证书的状态信息(如“有效”,“过期”等)。

由于客户端在等待查询结果前是阻塞的,OCSP查询过程耗时长短就影响了SSL阶段耗时。

执行OCSP协议的一次请求过程如下图

从图中可以看到,客户端会多出一次OCSP的查询过程。为了解决OCSP协议对性能的影响,OCSP Stapling协议应运而生,下面介绍下OCSP Stapling协议。

3.3.2 什么是OCSP Stapling协议?相比OCSP做了什么优化?

OCSP Stapling是将证书状态的查询过程从客户端迁移到服务端,由服务端低频执行OCSP协议请求CA服务器查询证书状态并将查询结果缓存起来,服务端在客户端请求SSL阶段时将证书查询结果返回给客户端。

执行OCSP Stapling协议的一次请求过程如下图

从图中可以看到,执行OCSP Stapling协议后客户端可以节省一次OCSP查询过程。

3.3.3 OCSP Stapling开启优化调研

友商使用OCSP Stapling的情况调研

调研友商的CDN资源请求OCSP Stapling使用情况,友商的CDN服务已开启OCSP Stapling,验证了OCSP Stapling的可行性。

友商的CDN服务是否OCSP Stapling生效的验证方法:

步骤1:查询友商CDN域名(如:cdn.xxx.com)的IP,可以使用dig命令

dig cdn.xxx.com

步骤2:通过openssl命令查看友商CDN域名OCSP Stapling状态

openssl s_client -connect 步骤1查到的ip:443 -servername cdn.xxx.com -status

结果1:OCSP Stapling生效图片如下:

可以看到OCSP Response Status:successful(0x0),代表OCSP Stapling已生效

结果2:OCSP Stapling未生效图片如下:

可以看到OCSP Response:no response sent,代表OCSP Stapling未生效

客户端双端OCSP Stapling兼容性调研

iOS:系统默认支持OCSP Stapling

Android:暂不支持OCSP过程

阿里云CDN兼容性:

与阿里云客服已确认阿里云CDN服务支持OCSP Stapling功能。如果客户端系统支持OCSP Stapling功能,则开启后OCSP Stapling功能生效;如果客户端系统不支持,依然支持使用OCSP方式正常请求。

线下测试:使用Debug包在线下环境分别开启OCSP Stapling与关闭OCSP Stapling请求CDN资源,均请求正常。主要覆盖这些方面:

1.反复验证:包括反复开启/关闭,App冷/热启动,App切前后端等操作链路;

2.业务主链路回归:覆盖社区首页、社区详情页、视频、交易首页、商品详情页、订单详情页等核心页面;

3.兼容性测试:覆盖App最近版本,主流机型、主流系统等。

3.3.4 OCSP Stapling开启优化方案

通过操作阿里云CDN控制台开启OCSP Stapling功能来实现SSL阶段耗时进一步优化。

变更执行:凌晨2点在阿里云CDN控制台操作开启OCSP Stapling

验证方案:如上文描述友商调研方法,使用openssl命令查看CDN域名cdn.poizon.com OCSP Stapling状态是否生效

监控方案:

1.网络监控平台:监控请求异常率、请求耗时等指标是否有异常波动情况;

2.阿里云CDN-实时监控:分钟级2xx,3xx,4xx,5xx状态码是否有异常波动情况。

3.3.5 OCSP Stapling开启优化效果

CDN cdn.poizon.com开启阿里云OCSP Stapling后iOS端耗时降低明显,Android端变化不大(Android:暂不支持OCSP过程,因此OCSP Stapling优化对Android暂无作用),优化前后数据:

平均耗时(仅建连)

iOS:565ms ->484ms,降低81ms

Android:401ms -> 360ms,降低41ms

SSL阶段耗时

iOS:97ms -> 87ms,降低10ms

Android:79ms -> 70ms,降低9ms

3.4 HTTP2.0升级

3.4.1 从Http协议版本维度进行监控数据分析

查看CDN域名cdn.poizon.com 2021.11.30号单日监控数据,发现双端同时存在Http2.0、Http1.1两种协议版本的请求,因此从Http一些版本的维度进行监控数据分析。

查看双端Http2.0与Http1.1占比

iOS:Http2.0占比51.98%,Http1.1占比48.01%

Android:Http2.0占比76.46%,Http1.1占比23.53%

可以看到双端都存在20%以上的Http1.1流量。

查看双端Http2.0与Http1.1各自的TCP复用率

iOS:Http2.0 TCP复用率9217%,Http1.1 TCP复用率396%

Android:Http2.0 TCP复用率2397%,Http1.1 TCP复用率681%

发现双端Http2.0的TCP复用率比Http1.1的TCP复用率高出几倍, iOS 端差不多高一个量级

注:TCP复用率 = TCP连接复用次数 / TCP建连成功次数

由于TCP每次重新建连都需要经过DNS解析、TCP三次握手、SSL四次握手阶段的耗时,而TCP连接复用时则节省了这三个阶段的耗时,复用TCP连接的CDN资源请求耗时更短。也就是说TCP复用率越高,CDN资源请求的平均耗时越短。

讲到这里,可能很多同学就提出了疑问,为什么Http2.0的TCP复用率可以达到这么高呢?下面我们简单介绍下Http2.0协议。

3.4.2 什么是Http2.0协议

Http2.0有哪些优势?相比Http1.1的区别是什么?

Http1.1协议仍是使用最广泛的Http协议,但其存在的痛点也众所周知,包括:

1.请求拥塞:并发的每个请求都需要一个TCP连接,并且最多6个,超过则会拥塞等待;

2.头部冗余:不支持头部压缩,且每次请求都会重复传递头部,造成带宽浪费并影响性能;

3.单向传输:仅支持客户端向服务端发送,不支持服务端主动向客户端发送;

4.明文传输:支持Http方式请求,数据明文传输,存在安全风险;

5.优先级受限:同一个TCP连接上仅支持串行发送,不支持高优先级请求率先发送,影响性能。

Http2.0协议是对http1.1协议的拓展和优化,引入了帧的概念,在应用层与传输层之间添加了二进制分帧层,针对性的提出了几点新特性:

1.多路复用:解决Http1.1请求拥塞的痛点,并发的多个请求支持在同一个TCP连接上进行传输,每个请求都会被拆分成一个个的帧,帧头信息会保存对应的请求信息,以二进制形式传输到对端后会根据帧头信息将请求数据进行重组;

2.头部压缩:解决Http1.1头部冗余的痛点,一方面使用HPACK算法对头部进行压缩减小传输体积,另一方面在双端维护Headers表,对已传输过的头部仅需携带对应key,避免重复传输;

3.服务端推送:解决Http1.1单向传输的痛点,允许服务端向客户端主动推送数据,如html请求时,服务端会主动向客户端推送相关的css,js文件,避免客户端多次请求,降低整体RT耗时;

4.二进制传输:解决Http1.1明文传输的痛点,数据被封装成帧,帧再以二进制形式进行传输;

5.支持优先级:解决Http1.1优先级受限的痛点,新建的流使用报文帧设置优先级,已创建的流使用优先级帧类型设置优先级,在资源有限的情况下使用优先级选择Stream流进行传输;

友商使用Http2.0情况调研

调研友商的CDN资源请求Http协议版本,友商App都使用的Http2.0协议,验证了Http2.0协议的可行性。

与TLS1.3协议友商调研方法类似,通过Chrome浏览器加载友商的图片,在DevTools窗口的Network面板可以看到使用的是h2协议。

3.4.3 Http2.0升级优化方案

对CDN域名cdn.poizon.com Http1.1协议版本请求的CDN边缘节点的IP分析后发现非阿里云CDN,与运维同学确认后得知CDN域名cdn.poizon.com切了40%流量在七牛云CDN,使用的Http1.1协议。

可以采用将这部分七牛云的流量进行Http2.0升级来提升CDN资源请求性能,执行线上变更将流量切回阿里云CDN(已开启Http2.0协议)。

3.4.4 Http2.0升级优化效果

CDN域名cdn.poizon.com流量切回阿里云后,https1.1流量已转为https2.0,https2.0流量占比双端均95%+,优化前后数据:

平均耗时

  1. iOS 248ms -> 221ms,降低27ms

  2. Android 350ms -> 329ms,降低21ms

TCP复用率

  1. iOS:841% -> 5127%,升高4286%

  1. Android:1441% -> 2160%,升高719%

4.小结

以上4个优化方向可以让你以较少的人力投入获得比较显著的CDN资源请求性能提升,但因涉及到线上变更,要注意做好线下回归测试,线上变更、验证、监控、还原方案。

最后,感谢运维,测试及相关参与同学在CDN资源请求优化过程中的协助。

文/Aix

关注得物技术,做最潮技术人!