要想提升 P2P 带宽节省率, 最直接的方式当然是压缩 CDN 带宽, 但简单粗暴的减少 CDN 下载势必会带来播放体验问题. 腾讯视频数据传输研发高级工程师严华梁在 LiveVideoStackCon 2019 深圳的演讲中详细介绍了腾讯视频针对 P2P 带宽节省的最新探索与实践.
文 / 严华梁
整理 / LiveVideoStack
PART1/P2P 技术项目背景
P2P 实际上是利用用户之间互相分享视频的数据, 来减少从 CDN 下载数据的量, 从而达到带宽节省的效果.
一般情况下, 在使用 P2P 进行带宽节省的基础上, 服务所需带宽的计算公式如上图所示: 带宽 = 播放量平均码率 * 平均播放时长 (1-P2P 带宽节省率). 观看视频的用户除了从平台服务器上调用数据, 还会从其他用户那里来调用数据.
腾讯视频业务在过去几年迎来了高速的发展, 用户规模不断提高, 无论是播放量还是视频平均码率都有明显的提升. 此时摆在我们面前的一大挑战就是: 如何持续提升 P2P 带宽节省率, 并做到 CDN 带宽成本保持较少增长?
上图展现了我们提升 P2P 带宽节省率的思路. 结合之前的带宽计算公式我们可知, 如果需要降低 CDN 的带宽成本, 最简单粗暴的方式就是减少 CDN 的下载, 但这样会带来诸如卡顿的音视频体验问题. 我们的思路是首先系统性地优化 P2P 网络的传输效率. 由于 P2P 网络是一个对端网络, 因此需要从下载端与上传端两个方面综合看待该项命题. 那么在完成对 P2P 的系统优化之后, 在此基础上我们还需要考虑更少的 CDN 下载, 接下来我们就分阶段思考如何实现这一目标.
PART2 / 如何提升 P2P 带宽节省率?
若想实现更快的 P2P 下载, 需要做的第一件事情便是传输协议的优化. 众所周知, 在 TCP 中存在一个慢启动阈值, 为了优化拥塞控制算法我们需要对慢启动阈值进行动态设定, 算法策略其实就是经典的 ssthresh=max(BDP, cwndα/10). 在此基础之上我们又引入两个策略: 丢包避免与丢包过滤. 丢包避免从降低丢包率入手, 也就是最近 RTT 大于 rttMin+(rttMax-rttMin) β/100,cwnd 不增加; 丢包过滤从提高吞吐率入手, 也就是最近 RTT 小于 rttMin+(rttMax-rttMin)* γ/100, cwnd 不退避. 上图展示了我们自研的 P2P 拥塞控制算法与 TCP Cubic 的对比结果, 红线代表 TCP Cubic 而蓝色则代表我们自研的 P2P CC. 从数据中可以看到当出现网络抖动时, TCP Cubic 对丢包和时延比较敏感, 滑动窗口抖动非常剧烈, 而 P2P CC 则相对平稳许多.
TCP 的拥塞控制尽管已经演化多年, 但仍旧存在较多问题. 这告诉我们一个道理: 没有一种拥塞控制算法能够适应所有的业务场景或者说网络场景. 因此我们希望通过结合应用场景来实现个性化的拥塞控制.
所谓的个性化拥塞控制其实就是依据播放时间线进行差异化传输. 如上图所示, 播放时间线从播放点开始梳理, 播放点往后开始读取数据. 那么离播放点越近的数据则会被优先读取到, 即优先级较高. 于是在这一区间段内我们采用比较激进的拥塞控制参数, 尽可能保证传输的效率而损失一部分丢包重传的优化; 在距离播放点较远的区段内, 采用另外一种策略 -- 优先考虑丢包率和重传率并降低吞吐率. 上图展示的是新旧算法 P2P 下载速度的对比, 我们可以看到相对于固定阈值的旧算法, 新算法尤其是在 FAST 与 MEDIUM 档有明显提升. 在网络下载效率方面, 优化后的整体重复下载率较之前有非常明显的提升.
解决完拥塞控制的相关命题, 接下来面对的是如何进行有效选种并高效利用. 最关键的一点便是如何评估种子的质量.
这里我们引入一套完整的基于 QoS 的选种淘汰机制: 第一项考察的指标是数据完整度, 例如在 PC 客户端的磁盘内存在一些缓存, PC 客户端上的数据相对更加完整, 这样便可在整个视频播放的过程中提供更高质量的上传数据; 第二项考察的指标为是否断连; 第三项是数据接收成功率, 其中包括丢包率; 最后一项指标是被冻结次数, 也就是当连接上一个比较好的种子之后, 对上传效率的影响是积极的. 但如果进行一次数据交互之后对端提供的反馈信令结果是忙碌, 那么可能是因为种子质量出色而连接的对象有些多. 在这种情况下, 该时间段内负载已经达到较为满负荷的状态, 有可能超过了硬件可承载的水平. 当有新的请求过来时, 会反馈忙碌的状态, 从而控制下载请求. 但由于该种子质量出色, 因此服务器会选择对该链路进行冻结处理, 暂时不向该端请求数据传输, 并保留对接的端口, 待该端不再忙碌之后继续请求下载数据.
随着智能路由器的普及, NAT 类型被限制得越来越严格, P2P 想找到一个质量出色的种子并成功连接的概率越来越低, 难度越来越大, 因此设计这样的保护机制可以确保种子物尽其用.
选种之后面临的问题是选片. 在 P2P 传输中, 一个流媒体文件会被做切片处理, 从而更充分地利用 UDP 进行传输. UDP 本身发送一个数据包会受 MTU 的影响, 例如以 64K 为一片, 切片一段文件, 并以不同颜色表示若干个文件片段的下载状态. 每一片应当分配给哪一个种子来实现 P2P 下载? 这是我们在选片算法当中需要考虑的问题.
结合时间线, 我们提出了一个被称为集中式协同选片算法的策略. 按照时间轴进行梳理, 离播放点近的数据是即将被播放的, 下载优先级最高. 这里的 "集中式" 就是指集中下载优先级高的数据, 从而保证整体播放的流畅."协同" 则是指多个种子对优先级高的某一区域数据进行协同下载, 例如前面几片分配给一个种子, 后面几片分配给另外一个种子. 如果简单粗暴地让 64K 数据直接向某一个种子提出下载请求, 那么一旦该种子下线或对应的网络中断, 那么 64K 的数据相当于被整体丢包, 假如丢包的数据处于距离播放点较近的位置, 短时间内又无法高效地下载, 就会出现播放的中断.
为了做到集中式协同下载, 我们引入了两个队列: 可下载块队列与正在下载块队列. 在 P2P 中, 通过种子之间的位图交换, 我们可以获知应当下载哪些块, 这便是可下载块队列. 正在下载块队列的大小是相对固定的, 也就是说对于任何一个种子, 如果在选片时发现正在下载的块没有完整下载完毕, 那么就会优先下载这一部分. 例如一个种子开始下载, 此时系统发现其他种子超时, 那么系统不会重新下载别的分片而是继续下载该种子后面的分片, 从而利用这种集中式协同的思路, 尽可能完整地下载某一块数据. 我们知道 UDP 的数据传输没有 TCP 那样严格依赖顺序, 而集中式协同的设计主要是为了按顺序尽可能快地将距离播放点比较近的数据下载下来, 从而实现 P2P 下载效率与播放体验的精准平衡.
全平台的视频介质统一至关重要, 大家知道广播电视行业需要牌照, 这样影视作品才能在 TV 端合法上线. 但腾讯没有这方面的牌照资质, 因此我们需要寻求外部牌照方合作. 而第三方合作就存在一个问题: 对方会要求在 TV 端播放时必须显示牌照方的水印, 而不能显示腾讯视频自己的水印.
一般情况下, 水印会被直接编码在原视频数据当中, 称为 "硬水印". 为了做到全平台统一, 我们则使用了软水印技术, 也就是将视频内容与水印分开. 同一个视频内容在不同的平台上, 介质完全一样而水印显示则根据场景改变, 从而满足不同场景的水印需求.
我们构建了一套系统性的种子质量提升方案: 在第一层, 系统会对一些无效的种子做过滤处理, 这里的 "无效种子" 更多的是指在一些限制条件下对种子的筛选择优, 如 ISP 过滤 (以避免对运营商网络不友好的跨运营商传输),NAT 类型过滤 (常规手段实现 NAT 穿透较为困难, 我们会尽可能选用对称型以减少在穿透方面的损耗), 平台过滤 (更多考虑移动端, 因为移动端存在运营商网络的限制), 连接数过滤.
结束第一层过滤之后, 我们会根据一些属性, 使用多属性权重打分决策算法对其进行处理. 这里的属性主要有在线时长 (能否提供稳定的在线上传), 上传能力 (如 100M,200M 带宽等),NAT 类型与地域就近. 完成加权打分之后, 我们会对种子进行一个质量等级的划分. 随后优先返回评分较高的种子, 这样可充分改善客户端的种子建连与下载效率.
为实现更多的 P2P 上传, 我们还需优化上传控制. 在 P2P 网络传输的早期, 例如大家在大学时可能用过 BT 下载, 如果宿舍里面有一个人正在进行 BT 下载, 那么其他人可能连常规的互联网访问都无法正常进行. 也就是说如果控制不好 P2P 的上传过程, 实际上会对 TCP 的 ACK 等普通网络传输过程带来不利影响, 因此我们希望实现更加出色的上传控制. 这里的优化借鉴了类 BBR 的思路, 也就是通过周期性地动态测速, 对每个 P2P 信道实时计算上行带宽累加, 并作为限速值进行上传动态限速控制, 限速机制采用 TCP 中匀速发送的机制, 从而降低瞬时大数据包对网络传输链路的冲击.
对于客户端来说, 通过信道连接不同种子, 我们这里测量的是不同信道的带宽情况, 并累加作为整体上传的限速值. 上图右侧可视化图表展示了动态测速方案的效果, 我们可以看出其整体波动均匀集中. 用户在使用客户端访问服务时可能会同时进行一些其他的上网行为, 例如看视频时点击某个网页. 测速图表中的 "PC 空闲时间" 就是指用户未使用鼠标, 键盘的时间, 如果侦测到鼠标, 键盘使用, 那么我们则认为用户在访问互联网其他服务. 根据测速结果我们可以看到, 随着空闲时间不断增加, 动态测速呈现一个缓慢上升的趋势, 也就是说动态测速可以感知并自适应用户其他访问互联网的行为, 并确保视频服务的可用.
在完成对 P2P 下载与上传的优化之后, 我们还需实现更少的 CDN 下载. 我们所做的第一件事就是优化 http 下载, 对此我们并未采用过于高深莫测的算法, 而更多采用的是策略优化 + 拥塞控制优化 (QUIC,BBR).
策略上的优化, 总体思想其实是多元 -- 第一项是 MSS 也就是 IP 直出和域名兜底. IP 直出是为了减少 DNS 解析所带来的耗时, 域名兜底则主要是为了适应运营商的切换, 如用户从中国电信的 Wi-Fi 网络切换到中国联通的 4G 移动网络, 此时原电信服务器的 IP 需要切换至联通服务器下的 IP 之上, 我们会对域名进行解析并实现兜底.
第二项是多 IP 竞速连接, 之前 IP 直出决定了有多个 IP 待选, 这里我们使用了多 IP 竞速连接以提高速度.
第三项是多链接加速, 现在大家提到比较多的一个是 MP TCP, 也就是实现 Wi-Fi 网卡与运营商网卡的组合加速.
在策略优化的基础上, 我们进行了拥塞控制优化, 如使用 QUIC,BBR 等.
若想实现更少的 CDN 下载, 除了优化 http, 必不可少的一项举措是合理利用 CDN 资源.
结合业务特性, 我们进行了系统调度的优化: 首先尝试深度整合业务, 例如用户访问腾讯视频, 如果是非会员那么会在正片开始之前看到一段时间较长的广告. 在广告播放期间系统就可利用 P2P 网络预先下载正片数据, 在此期间 CDN 并未被使用. 除此之外在播放专辑画面时, 如果专辑中上一集即将播放结束, 那么下一集即可开始预加载. 当然还有一种情况是用户退出当前正片之后, 可能需要重新点击打开重复观看, 此时系统会对播放点数据做缓存处理, 从而实现当用户想要再次打开观看时, 系统可快速从本地加载数据并快速开始播放.
当然, 如果是会员无广告的情况, 为了保证播放体验我们还是会优先选择 CDN 下载数据, 从而保证快速启动播放. 在这里我们构建了一套网络预测模型, 结合历史下载速度, 实时下载速度与当前视频码率综合做出决策, 判断启动播放究竟需要多长时间, 并尽可能降低 CDN 的下载时长. 例如当用户使用光纤网络时, 由于网络带宽资源充裕, 下载速度较高, 即便没有 P2P,CDN 也可快速下载所需数据并实现快速启动播放.
除以上两点之外, 我们还会从用户行为入手. 上图右侧图线是我们与香港中文大学进行的联合研究的结果: 不同的媒体类型如电影, 电视剧, 综艺等, 其视频用户中断播放的位置也不尽相同. 对于不同类型的视频用户在某一个时间段离开的概率不同, 且存在一定规律. 通过数据分析我们可以基于此在下载的时长控制方面进行一些针对性处理.
实现更少 CDN 下载的最后一点是多源体系建设. 由于 CDN 价格高昂, 因此我们应当科学调配内容与承载网络类型之间的关系, 从而实现产品服务与成本控制的精准平衡.
上图左侧展示了 CDN 的大概拓扑结构, 从上到下依次是距离用户比较远的服务器, 城市或社区的机房, 家用路由器与用户终端, 与用户之间的距离由远及近. 随着 5G 时代的到来, 大家经常提到的一个词是移动边缘计算也就是 MEC, 未来 5G 基站即可承担一部分机房的角色. 大家总是强调 5G 技术的高带宽低延时, 如果未来我们的视频内容直接下沉到基站, 借助 5G 网络访问就可达到类似于局域网的效果, 其所能达到的速度是惊人的. 如果 CDN 距离用户较远, 那么本身就存在一个传输链路上的损耗; 我们尝试尽可能缩短用户与内容之间的距离, 进一步突破互联网传输技术对用户体验的桎梏.
PART3 / 总结
P2P 节省率 = P2P 带宽 / (P2P 带宽 + CDN 带宽), 要想提升 P2P 带宽节省率, 最直接的方式当然是直接压缩 CDN 带宽, 如减少 CDN 下载; 但是简单粗暴的减少 CDN 下载势必会带来播放体验问题, 所以我们的思路是先优化 P2P 网络, 在 P2P 网络优化下载的效率和稳定性提升之后, 再来合理的减少 CDN 下载.
来源: https://www.qcloud.com/developer/article/1605759