
一、背景
我们平时在看抖音快手视频的时候,如果滑动到某个视频画面一直几s不动的时候,大概率就会划走了,所以在短视频项目中,画面卡顿是非常影响用户体验的,启播速度越快,就越能留住用户。
启播速度简单来说就是从调用开始播放到首帧上屏的时间,大致可分为两部分:
-
视频解码耗时
视频文件下载耗时
本文主要从运维排查问题的角度,从网络这部分的各个环节入手,结合vivo短视频的具体案例,给大家分享下优化过程。
二、用户访问链路
我们先梳理下一次完整的网络请求过程,以客户端视角为例,如下图所示:
-
TCP连接建立:与服务器IP建立连接即tcp三次握手。
-
TLS握手:客户端向服务器索要并验证服务器的公钥,双方协商生产「会话秘钥」并进行加密通信。
-
CDN响应:将内容资源分发到位于多个地理位置机房中的服务器上并返回给客户端。
DNS域名解析:获取服务器的IP地址。
针对以上阶段,分别讲下vivo短视频是如何进行优化的。
三、DNS域名解析
3.1 域名的层级关系
句点来分隔的,比如 www.server.com,这里的句点代表了不同层次之间的界限。在域名中,越靠右的位置表示其层级越高。根域是在最顶层,它的下一层就是 com 顶级域,再下面是 server.com。
-
顶级域 DNS 服务器(com)
-
权威 DNS 服务器(server.com)
根DNS服务器
根域的 DNS 服务器信息保存在互联网中所有的 DNS 服务器中。这样一来,任何 DNS 服务器就都可以找到并访问根域 DNS 服务器了。
因此,客户端只要能够找到任意一台 DNS 服务器,就可以通过它找到根域 DNS 服务器,然后再一路顺藤摸瓜找到位于下层的某台目标 DNS 服务器。
3.2 域名解析的工作流程
浏览器首先看一下自己的缓存里有没有,如果没有就向操作系统的缓存要,还没有就检查本机域名解析文件 hosts,如果还是没有,就会 DNS 服务器进行查询,查询的过程如下:
-
本地域名服务器收到客户端的请求后,如果缓存里的表格能找到 www.server.com,则它直接返回 IP 地址。如果没有,本地 DNS 会去问它的根域名服务器:“老大,能告诉我 www.server.com 的 IP 地址吗?” 根域名服务器是最高层次的,它不直接用于域名解析,但能指明一条道路。
-
根 DNS 收到来自本地 DNS 的请求后,发现后置是 .com,说:“www.server.com 这个域名归 .com 区域管理”,我给你 .com 顶级域名服务器地址给你,你去问问它吧。”
-
本地 DNS 收到顶级域名服务器的地址后,发起请求问“老二,你能告诉我 www.server.com 的 IP 地址吗?”
-
顶级域名服务器说:“我给你负责 www.server.com 区域的权威 DNS 服务器的地址,你去问它应该能问到”。
-
本地 DNS 于是转向问权威 DNS 服务器:“老三,www.server.com对应的IP是啥呀?” server.com 的权威 DNS 服务器,它是域名解析结果的原出处。为啥叫权威呢?就是我的域名我做主。
-
权威 DNS 服务器查询后将对应的 IP 地址 X.X.X.X 告诉本地 DNS。
-
本地 DNS 再将 IP 地址返回客户端,客户端和目标建立连接,同时本地 DNS 缓存该 IP 地址,这样下一次的解析同一个域名就不需要做 DNS 的迭代查询了。
客户端首先会发出一个 DNS 请求,问 www.server.com 的 IP 是啥,并发给本地 DNS 服务器(也就是客户端的 TCP/IP 设置中填写的 DNS 服务器地址)。
至此,我们完成了 DNS 的解析过程。现在总结一下,整个过程画成了一个图。
DNS 域名解析的过程蛮有意思的,整个过程就和我们日常生活中找人问路的过程类似,只指路不带路。
3.3 vivo短视频所做的优化
弄清了域名解析的工作流程,将vivo域名和头部厂商域名进行对比分析,发现vivo短视频域名解析耗时不稳定,波动范围很大,怀疑是某些地区用户访问量少,本地DNS服务器缓存命中率低导致的,因此我们的优化思路就是 提高本地DNS缓存命中率。
如上图所示,提高DNS缓存命中率一个简单的办法就是添加全国范围内的拨测任务,来进行DNS加热。
通过对调整前后的DNS解析时间进行比较,可以看到耗时降低了30ms左右。
四、HTTP性能
HTTP 协议是基于 TCP/IP,并且使用了「请求 - 应答」的通信模式,所以性能的关键就在这两点里。
1. 长连接
为了解决上述 TCP 连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。
2. 管道网络传输
即可在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
但是服务器还是按照顺序,先回应 A 请求,完成后再回应 B 请求。要是 前面的回应特别慢,后面就会有许多请求排队等着。这称为「队头堵塞」。
3. 队头阻塞
因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据,这也就是「队头阻塞」。好比上班的路上塞车。
4.1 HTTP/1.1 相比 HTTP/1.0 性能上的改进:
-
支持 管道(pipeline)网络传输,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
但 HTTP/1.1 还是有性能瓶颈: