流媒体拥塞控制与流控
音视频流的传输强调低时延,若不可得则要确保低抖动,最后才是吞吐:
- 网络质量好,可保证低时延下的高清晰度;
- 网络质量稍差,少量 buffer 吸收抖动;
- 网络质量很差,降低码率,少发点数据;
- 没一个场景在乎吞吐,因为码率要适应网络,而不是反过来…
在现实中,“尽可能多发一点” 的认知依然在起作用,这想法来自早期 “块数据” 的传输逻辑,在相对较大的时间尺度上调速,《TCP/IP 详解》卷 1 中有讲到,而流媒体传输则需要在 ms 级别甚至更小的时间尺度上调速,于是各种弄巧成拙的错配算法铺天盖地。
sender 端拥塞控制逐渐向上 “紧贴” 业务,强调与编解码结合,我自己也是这观点,部分原因在于流媒体传输逻辑和传输层拥塞控制太难也不应解耦,但转念一想,这个难解耦是结果而不是原因。如果关联编解码,事情就会更复杂,所以把时延的职责更多往下层压。
如果传输层认为该少发一点数据,应用层应该降低码率,反之应该增加码率,否则就会错配,造成应用层时延抖动。这事之所以难,因为大家都想做好它,但却总做不好,可观测性能的提升部分来自实验室约束,部分来自网络质量,部分来自运气,算法本身的贡献很小。否则早轰动业界了,事实上 2015 年以来业内相关,除了 BBR 具有足够规模的现网影响力,其它的都停留在学术圈或实验室。
一个很简单的解法十几年前就存在了,在 sender 应用层和传输层之间铺垫一个固定 buffer,应用层持续观测 buffer 水位,调整编码速率,以保持 buffer 水平一直保持稳定,拥塞控制则完全交给传输层。这种解法被普遍唾弃的原因在于它 “显式引入了时延”,与 “极低时延” 的宣传话术相违背,因此,即使做不到也要硬做,挤出一丁点想法就 pr 的卷状生态就形成了。
我前面屡次强调一个观点,由于交易的本质,设计和优化的过程本就是不断权衡的过程,优化的收益需要放弃一些别的收益,最终的工程方案一定不是最优的,而是足够好的。对于流媒体传输,抖动危害更大,而稍微的 buffer 时延便可以吸收大量抖动。这种基于交换的解法也足够简单,但简单是原罪。
日常生活中有一个很好的例子解释持续观测 buffer 水位的例子,就是输液管中间的墨菲氏滴管:
不断调节滴管下游的流速,滴管的水位在气压作用下保持恒定,这就是典型的流控。TCP 的端到端流控也是采用了这种方法,receiver 不断反馈 rcv buffer 的 “水位” rwnd,只是墨菲氏滴管靠的是气压。
说起流控,就得说数据中心,而流控的意义更多在逐跳行为,因此广域网不适合做流控,但数据中心能。
如果把持续观测下层 buffer 水位的算法在分层网络各层间递归做下去,最终得到的就是一个 link 级的流控方案,相当于将大量墨菲氏滴管级联或组成胖树结构,仍能观测到上述动图里现象,每一个滴管都维持着稳定的平衡水位。而这个纯流控网络自然不再需要拥塞控制,它是天然无拥塞的。
现实中,InfiniBand 是一个 link 级流控方案实例,而 RoCEv2 是一个松散版本,它采用 PFC Pause 帧在网络已经拥塞时迅速阻滞部分流量,而不是全程观测并平滑阻滞,显示 “剩余车位 2” 的停车场入口的排队等待几乎一定没有显示 “车位已满” 的停车场入口更严重。
传输网络非常适用系统动力学建模,而系统由源,汇,存量,流量组成,而 “流量刻画各存量水平之间的反馈”,以下是《模型思维》(昨天发朋友圈推荐过这书)一书中的一个配图,大致说一下意思:
系统动力学模型强调,存量决定行为,流量负责改变行为,但千万不要试图让流量决定行为。比如一个屋子的室温是空调的设置决定的,而不是开窗关窗决定的。
善作计量者总是试图发现各种流量之间的关系,并以此为定论决定此后的流量,但这是徒劳的,他们不过在寻找一些不存在或至少不稳定的关系。事实上,任何一个系统的流量和其它流量之间都没有稳定的关系,流量只受存量影响。
数据和 buffer 就是存量,而 link 级的流控就是流量引起的反馈,端到端传输控制相当于丢失了很多反馈,那也就只好由端自行发现并处理异常(丢包 or 时延抖动)了,这就是拥塞控制。
浙江温州皮鞋湿,下雨进水不会胖。