得物技术网络优化 -CDN 资源请求优化实践
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
2. 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 升级最佳实践》https://mp.weixin.qq.com/s/C0dfQ52bWNOAWLkSC1f-4w
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%
2. Android:1441% -> 2160%,升高 719%
4.小结
以上 4 个优化方向可以让你以较少的人力投入获得比较显著的 CDN 资源请求性能提升,但因涉及到线上变更,要注意做好线下回归测试,线上变更、验证、监控、还原方案。
最后,感谢运维,测试及相关参与同学在 CDN 资源请求优化过程中的协助。
文/Aix
关注得物技术,做最潮技术人!
版权声明: 本文为 InfoQ 作者【得物技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/43d83da8a3353ba9df73630aa】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。







评论