本文为「Dev for Dev 专栏」系列内容,作者为声网大后端传输协议负责人 夏天。
针对实时互动应用对网络传输带来的新需求和新挑战,声网通过将实时互动中的应用层业务需求与传输策略的分层和解耦,于 2019 年自研内部私有的传输层协议 Agora Universal Transport(AUT),将异构网络下的各种传输控制能力汇聚起来,并于 2021 ~ 2022 年开始逐步大规模落地在各项业务中,用一套传输协议/框架解决各项业务不同的传输需求。
相关内容分为上下两篇,在上一篇内容《声网自研传输层协议 AUT 的落地实践》中,我们介绍声网 AUT 传输协议的诞生和在实时互动业务场景下的应用。本篇从协议的演进和落地过程中,抽象地总结 AUT 的经验,并对 AUT 以及未来实时互动网络传输进行展望。
AUT 的研发到大规模落地历时 3 年,传输协议的设计与实现兼具工程与算法的双重挑战,同时作为一项底层且抽象出来的技术,在实时互动的各场景落地的过程中又有着方方面面具体的问题,过程不可谓不艰辛。在此为我们的过往工作做些复盘和整理,抛砖引玉,为后续类似工作积累经验。
由于实际网络中的场景纷繁复杂,某个场景中的算法改动可能会导致在其他场景中不适配的问题,同时 AUT 由于服务于多个不同的业务,还需要避免业务之间产生影响。所以在 AUT 的算法设计中,我们的主要思路是对于新发现的问题先明确识别,在识别后再针对性的解决,以避免影响其他场景;通过可配置的方式、用灰度试验和数据驱动分析实际结果来评估算法设计的优劣。
在算法的设计中,由于 AUT 内的弱网对抗模块较多,各个模块如果都独立维护自己的状态和逻辑,会产生很多的冗余代码。一个典型场景是,某个模块正在分析的数据也是其他很多模块需要用到的,但触发算法决策的时机却千奇百怪各不相同。经过对该问题的分析后,我们决定将算法模块拆分为客观的数据统计模块和主观的决策处理模块,然后以事件驱动来触发各个不同的决策处理模块进行算法决策,这样数据统计能做到最大程度复用,各算法的关注点也变得清晰明确。
在没有 AUT 之前,传输和应用层的逻辑是紧密耦合的,紧密耦合虽然可移植性差,但是单从这一项业务的传输效果上来说却能够做到最好,因为很多业务信息可以非常方便共享互通。从 AUT 开始实现之初,我们就在思考如何既能够做到独立出来传输层协议和框架,又能够与各应用层一起将传输效果做到最优。最终,我们探索出来的思路是机制上深度耦合、工程上足够抽象。
首先从业务出发,从结果上我们仍然要对一个传输机制的最优处理方式保持不变,不能因为分层之后就忽略一些先验的知识和信息:例如视频传输中一整个帧需要一起处理,假如帧中间少了一块数据,就不能处理;那么在独立出来传输层后,也不能丢失这个整块信息,需要根据这个信息来决策如何传输块中的每一个包。所以从传输机制上,仍然要尽可能多的利用应用层提供的信息,以便把最终结果做到极致。
与此同时,工程上独立出来的传输层,不应该去理解视频中的帧是什么,这时候就需要抽象的去理解:对应用层是视频的帧,而对于传输层就是一个整块数据。传输层完成的事情就是如何将一整块数据的传输做到最优,那么由此对于“块数据”的传输策略就独立了出来──它可以被用在很多场景中,视频只是其中一个,其他例如传输加密的证书、图片、大段的信息,我们都可以使用同样的策略,这便是工程实现中抽象理解带来的好处。
如何做到在 AUT 落地在公司的各项业务中使用一套框架应对各个需求,是个很大的难题。在解决这个问题上,我们逐步探索出场景化传输的思路:首先明确自身的各项能力,然后分析并提取出典型使用场景(网络场景 + 业务需求)作为先验知识,再针对不同使用场景使用针对性能力完成传输需求。
例如典型的场景包括:
● 无线传输/有线传输;有线传输中的网络波动总体而言较少,那么我们可以简化很多传输策略、以提高性能;无线传输中多由于信道的竞争而表现出网络抖动较大、变化较为频繁,这时候需要根据具体的无线传输网络做特定的适配,例如根据网络抖动动态对发送策略进行补偿。
● 实时数据传输(RTC)/非实时数据传输(File/Report);实时传输中更强调数据的时效性,对于错误恢复要更激进甚至提前避免;非实时传输则尽量避免过于激进而对用户的整体网络使用情况产生较大影响。
● 单连接大流量传输(FPA)/多连接稀疏流量传输(S2S);单连接大流量传输可以做更多的聚合处理工作,而多链接稀疏流量则应避免连接空闲状态带来的开销。
● 长链接持续数据传输(Proxy)/短链接请求应答式传输(LBS Request);长链接传输可以开启 MTU 探测、附带发送部分额外信息、使用连接的前后上下文等以减少协议 overhead;而短链接请求应答式传输则可以对应用数据做更多额外传输保证,以避免数据丢失导致连接持续过长。
不同场景中对实时性/可靠性/弱网对抗能力的要求大不相同,我们的传输策略针对场景,而一个场景又能能够映射到其他多个具有共性的业务中,那么针对这个场景的传输优化就能够做到复用,而不再是针对一个个具体的业务去做定向优化。
传输协议的演进离不开自身的质量保证体系,只有具备稳定有效的质量保证体系,才能让协议的演进持续保持高效,否则完成技术改进也无法验证正确性,出现了问题也无从调查。
1.可视化内部逻辑的影响
传输协议的问题调查有其特殊性:传输中的包可能会很多,而每个包的发送和接收都可能会影响内部的状态和逻辑,同时内部模块和算法模块较多,逻辑链条可能会很长,跨模块的状态互相产生的影响光使用断点很难追踪长期的影响关系和结果。
这时一个比较好的办法,就是提供可视化工具,通过通用模块根据 log dump 内部信息,将内部各种状态做成可视化图表,能够极大方便对内部各变量的相互影响关系进行追踪,很多问题能够一目了然。
2.重现/自测各种网络场景
传输的网络状态转瞬即逝,对于各种网络状态的模拟和重现同样十分重要,我们使用两个层面的工具对网络状态进行重现:
● 使用系统层面相关工具(TC等),对较为复杂弱网场景进行模拟(具备复杂的弱网模拟能力,同时从时间/资源的开销上也更大);
● 使用内部仿真模块(simulator),从单元测试层面对较为明确的弱网场景进行仿真(模拟能力较弱,但是开销较低);
这两个层面的工具形成互补,从不同的维度对网络状态进行重现,为 AUT 进行内部调试提供了可靠的依据。
3.保证代码的健壮性
由于在公司内广泛应用,同时暴露在公网上接收各种不可预知的输入,代码的健壮性同样需要有效的保证。
● 使用 fuzz 测试自动化模拟各种配置/接口/网络包的正常或异常输入,确保稳定性。fuzz 测试对于传输协议而言是一个非常好的工具,机器的运算力和对代码路径的判断相比人为思考测试用例在覆盖面上能够做到更加全面;
● 极端场景覆盖,通过长时间和极端异常网络来进行压力测试。极端场景往往是最典型的 corner case,很多设计时漏掉的边界场景,在极端场景测试中都能够出现,所以永远不要放过。
传输控制本身是一项非常底层的技术,可以说是很多上层应用的基石,在底层技术的研发中,由于遇到的问题非常多,时常陷入的一个怪圈就是容易自己给自己找一些问题去思考并花很多时间解决,这其中有些问题是具有前瞻性和实际价值的,但也有很多可能是脱离实际或至少在当前阶段是脱离实际的。这导致的一个结果就是技术演技与实际落地完全脱钩,技术演进的很好,但是在具体业务上很难产生实际价值,甚至可能做了一个完全没有业务需要的功能,费时费力却不讨好。
在 AUT 的演进过程中我们就有过类似的经历,后续我们就非常注重其中每项技术在具体业务场景中产生的实际价值,确保做出来的东西一定要放在具体应用场景中落地,这样有实际的应用场景,就会产生更实际的问题,这些问题的出现反过来又更好地帮助了技术的迭代,这样既能产生实际价值、又进行了技术演进,避免了闭门造车。
AUT 在各个场景的落地绝非结束,而是一个新的开始,后续对于网络和传输的相关工作仍有很多方向等待我们探索。
在各项业务中独立出传输层以后,使得我们获取了更为纯粹的各地用户网络数据,结果收取/分析/建模之后,网络数据能够为业务上提供很多支持,例如:
● 传输控制:使用用户网络数据来改善传输中的算法;
● 用户分配:让用户接入到最合适的运营商/边缘中;
● 网络诊断:根据当地/当运营商典型的网络模型,分析用户网络问题;
● 实验仿真:构建更贴近用户真实网络的弱网环境。
近年来机器学习在实时音视频传输中的应用也是层出不穷──多在拥塞控制算法中有些尝试。下图是我们内部的机器学习算法的实验结果,可以看到相比于 Paper 中的实验结果,我们内部的算法的带宽估计结果更加逼近 Optimal:
机器学习的算法非常依赖数据集,在完成更充分的数据收集工作后,我们相信机器学习在网路传输中会发挥出更大的价值。
多路径传输是未来的大势所趋,AUT 内部也同步在做相应的支持,目前正处在逐步落地的阶段。下图是一个我们目前在实验室测试:multipath 版本使用 Wi-Fi 和移动数据两个出口进行传输,singlepath 版本仅使用 Wi-Fi,我们仅在 Wi-Fi 链路下添加弱网。
结果显示,multipath 版本的视频延迟基本不受影响,而 singlepath 版本的延迟则随着弱网条件跌宕起伏。
AUT 中的各个弱网对抗模块从一开始就考虑到了通用性,做到足够模块化,输入也与协议本身完全无关,使得这些弱网模块可以非常容易地移殖到其他协议。
例如我们现在已经在 WebRTC 服务中使用了 AUT 内的拥塞控制模块,以改进原生拥塞控制的很多问题;同时 QUIC 在标准化后应用场景也越来越广泛,AUT 内的弱网对抗模块后续也会逐步迁移到公司内部的 QUIC 协议栈中,以增强 QUIC 的网络分析及弱网对抗能力。
综上所述,AUT 的诞生和迭代是一个从业务中来、到应用中去的过程。作为一个底层的协议,AUT 从声网繁杂的业务场景中抽象出了共性的网络传输需求,同时在工程层面,让底层算法与上层应用的耦合逻辑更具普适性;在模块化的设计理念下,AUT 也更容易整合到广泛使用的公有协议中,这也为 AUT 未来的发展打开了想象之门。
关于 Dev for Dev
Dev for Dev 专栏全称为 Developer for Developer,该专栏是声网与 RTC 开发者社区共同发起的开发者互动创新实践活动。
透过工程师视角的技术分享、交流碰撞、项目共建等多种形式,汇聚开发者的力量,挖掘和传递最具价值的技术内容和项目,全面释放技术的创造力。