28

谈谈网络通信中的流量整形-Jhuster的专栏

 4 years ago
source link: https://blog.51cto.com/ticktick/2473071
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

谈谈网络通信中的流量整形

前面的两篇文章《谈谈网络通信中的 ACK、NACK 和 REX》《谈谈网络通信中的 FEC 基础》介绍了网络通信中的丢包重传和 FEC 的相关理论和方法,他们都是在网络发生丢包的情况下的补救措施,本文则往前进一步,介绍下如何通过流量整形技术,尽可能地避免网络发生丢包。

从堵车说起

v2-dbd54149c8a9baf674a0237ea5623f5d_hd.png

堵车的原因有很多种,我们先聊聊图中的这种:假设某公路是 3 股道,也就是说,每时刻能同时进入该公路的车辆并行是 3 辆,那么,如果某一时间段,同时试图进入该公路的车辆超过 3 辆,则必然会出现由于公路的承载能力不够带来的 “堵车”。

v2-e3fd9186c204581fb255c15e64838d65_hd.png

网络传输也类似,假设网络带宽是 2Mbps,如果在每秒硬塞给网络的数据包 > 2Mbps,网络通道也会受不了。不过它的表现形式与公路不一样的地方在于:超出网络承载能力的数据包,可能会被网卡/路由器/交换机给丢掉,即我们常说的丢包(loss)。

对于网络传输而言,丢包带来的成本是很高的,因为一些重要的数据包丢失后,是需要 “重传” 的,而 “重传” 太多,来回反复会增加了数据传输的延时,也会进一步恶化网络负荷,最终极大地降低了传输的效率。

因此,我们需要从根本上尽可能地减少 “丢包” 的产生,简单来说,就是控制单位时间内送入网络传输的数据量,尽量平滑且不要超过网络带宽承载能力。

控制对象

既然要控制送入网络传输的数据量,就得先找到数据是怎么产生的,又是在通过哪个环节送入到网络的。

DraggedImage.png

如图,音视频传输的数据 “源头” ,无外乎就是本地的音视频文件、麦克风采集的音频流、摄像头采集的视频流、桌面采集到的屏幕流等,它们经过编码压缩和封包处理,然后经过 “发送模块” 送入到网络中。

设置和修改采集的配置(如:分辨率、帧率)、编码器的配置(如:GOP 间隔、码率)等,是可以减少实时产生的总数据量的,但是数据的产生并不是 “平滑” 的,特别是视频流/屏幕流,画面的突变,会带来数据量的突变,因此,送入到 “发送模块” 的数据量,也并不会总是 “平滑” 的。

从上面的 “堵车” 理论,为了避免丢包,我们需要尽可能地将数据 “平滑” 地送入网络中,因此,“流量整形” 在此派上了用场,它作用于 “发送模块”,目标是调整数据传输的平均速率,防止突发性的流量暴增导致网络拥塞和丢包。

流量整形

如何平输入和输出,一个最容易想到方法,就是增加 “缓冲”,让输入的数据先进入 “缓冲区” ,然后用恒定的 “速率” 从缓冲区取数据输出。这种方法称之为 “漏桶算法”。

漏桶算法(Leaky Bucket)

v2-da28afda819a75f0cd11aa4c5e05512b_hd.png

如图,使用一个 packet buffer(漏桶),把所有输入的 packet 缓存起来。

设置一个目标的输出码率(比如:3Mbps),固定的时间间隔(比如:10ms),读取 packet buffer(漏桶)中固定数量的 packet(如:3Mbit * 10ms / 1000 = 0.03Mbit)进行网络发送。注:如果某时刻缓冲区没有数据,则不用发送了。

漏桶算法的缺点

漏桶算法有一个明显的缺点,因为非常精准的网络带宽无法预判,那么假设你设置了一个比较小的目标码率(如 3Mbps),可能小于真实的网络带宽(如 10Mbps),这时,如果业务上产生了一些突发的流量,真实的网络带宽本可以允许更快地完成发送,但经过了漏桶算法后,依然会以恒定的目标码率慢慢地发送。所以说,漏桶算法无法充分用满网络资源来降低传输延时。

解决方案有 2 个:

  1. 先慢启动,然后将漏桶的目标码率持续上探,直到出现网络恶化(如:丢包增多)后再降下来,如此反复,维持一个动态平衡,使得漏桶算法的目标码率持续无限逼近网络的承载能力

  2. 改进漏桶算法,允许其在执行过程中,偶尔出现一些超过预设平均值的突发传输能力,用于应对业务上的流量突发,即:令牌桶算法

令牌桶算法(Token Bucket)

v2-c4cda3c67c50d6e4f01f6179dafe3991_hd.png

令牌桶算法在漏桶算法基础上,提出一个改进,就是新增了 “令牌” 和 “令牌桶”。

“令牌” 代表着允许传输的字节数量,我们以固定的时间间隔(比如:10ms)产生并送入 “令牌” 到  “令牌桶”,“令牌桶” 设置一个  “令牌” 数量上限(满了没有消耗就丢掉新增的令牌),因此,一次传输最大的允许突增的字节数 = M x B

发送模块,以固定 t ms 的时间间隔去读取 packet buffer,读取的字节数 X 必须接近但小于等于当前 “令牌桶” 中允许传输的字节数(即:“令牌桶” 里剩余的  “令牌个数” x B)。并且,传输完了多少字节,则删除掉 “令牌桶” 里对应个数的 “令牌”。

这种方法解决突发流量的关键点在哪呢 ?

在于 “令牌” 是可以积累的,可能缓冲区在前 N ms 都没有突发的数据,这时,“令牌” 依然在产生,并且被积累在了 “令牌桶”,一旦缓冲区突增了大量的数据,则可以在短时间内快速消费掉。当然,为了防止突破网络承载能力导致丢包,“令牌桶” 的最大 “令牌数量” 也相应做了一些限制。

小结

关于网络通信中的流量整形就简单介绍到这里了,“漏桶算法” 和 “令牌桶算法” 其实在很多的地方都有使用,比如服务端的限流降级,比如音视频的平滑丢帧等等,当然,也还有一些基于这些算法的各种改进策略,这里就不一一介绍了,欢迎大家来信 [email protected] 交流,另外,也欢迎大家关注我的新浪微博 @卢_俊 或者 微信公众号 @Jhuster 获取最新的文章和资讯。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK