linux中动态队列管理机制(AQM):CoDel

来源:互联网 发布:java软件工程师资格证 编辑:程序博客网 时间:2024/05/29 09:44

这里根据一份官方draftcodel进行深入分析。

 

1. 介绍:

最近几十年的研究表明,队列管理的必要性非常明显。自从80年代初到现在,IETF社区就一直讨论“持续完全缓冲队列”的问题。端到端的工作组从1998年就一直要求部署主动队列管理来解决缓冲区的问题,并且受摩尔定律的影响,缓冲池呈指数级增长,因此这个问题更加严重;并且部署AQM的努力受配置困难以及易造成网络利用率的影响而受阻。但是,最近bufferbloat问题越来越严重对整个互联网,尤其是在消费者的边缘,即用户接入的最后一跳。特别是,现在由于现在用户使用互联网的增加,动态队列管理变得更加重要,主要在于高质量的视频流以及高实时性的VoIP以及游戏业务体验。并且像Google这样的大型内容提供商已经发现,bufferbloat现象无处不在,并且对用户的网络性能造成了很大的影响,为了解决bufferbloat问题,主要采用一种AQM的方案,即通过动态队列管理的方案,来对过量的缓冲问题进行修复。

由于对网络缓冲区中分组队列的误解,导致有效的主动队列管理开发和部署收到持续性的阻碍。缓冲区有助于吸收分组的突发,比如缓冲区有助于合理的分组网络的行为,比如传输会话的瞬态启动以及共享链路的数量的变化以及速率的短期不匹配;但是,有些行为可能会导致队列被填充,并且效果不尽人意。因此,要了解动态队列管理,分清楚“好队列”与“坏队列”之间的差异至关重要。

过去二十年来,已经开发了许多主动队列管理(AQM)的方法,但由于性能问题,没有一个广泛部署。 当设计错误的队列概念模型时,AQM的操作范围有限,需要大量的配置调整,并且经常损害而不是提高性能。 今天,对有效AQM的要求更高:许多网络设备必须在一系列带宽上工作,这是由于链路变化或由于设备的移动性。CoDel方法旨在实现以下目标:

无参数操作:对于使用者或用户不需要去调节,能够自动调节

“好队列”“坏队列”采用不同的操作方案,即保持低延迟,同时允许必要的流量突发。

控制时延,同时对,同时对看路速率以及流量负载不敏感,这个目标主要是为了,在控制时延的基础上不对网络流量造成影响。

适应动态变化的链路速率,对网络的利用率不构成影响。

简单高效的实现。

Codel5个主要的创新相较于之前的AQM方案:

使用本地的最小队列来跟踪网络的拥塞(坏队列)。

使用跟踪统计量的有效状态量进行表示。

使用分组逗留时间观察到达的分组数据,而不是分组,字节或者速率。

使用最大化的网络利用率。

实时的状态控制器。

Codel根据往返时间的测量进行配置,这个时间的阈值根据正常情况下设置为100ms。在不改变阈值的情况下,通过大量的实验分析,该阈值可以使Codel算法工作在各种各样的条件下,具有不同链接以及全方位的往返时延。

Codel已经在Linux中得到高效的实现。

 

队列管理的基础

二十年的队列管理工作未能产生一种可以在互联网上广泛部署的方法。也就是说,现有的AQM已经能够减少排队延误,但只能以不正当的链路利用和/或公平的成本。队列管理的核心是“号队列”和“坏队列”的概念,并寻找摆脱坏队列(仅增加延迟)的方法,同时保持好的队列(提供良好的利用率)。 本节介绍排队的优缺点,涵盖CoDel构建模块,可用于管理数据包缓冲区,使其队列处于“好队列”的范围。

数据包队列形成在面向瓶颈链路的缓冲器中,即线路速率从高到低,或者许多链路收敛。众所周知的带宽延迟产品(有时称为“管道尺寸”)是瓶颈的带宽乘以发送者-接收者往返延迟,并且是两台主机之间必须运行的数据量,以便运行100%利用率的瓶颈。为了探索如何形成队列,考虑一个长时间的TCP连接,一个25个数据包窗口通过带有20个数据包的带宽延迟产品的连接进行发送。在数据包的初始突发之后,连接将稳定在5个分组(+/- 1)的队列中;这种缓冲队列大小由窗口大小和管道大小之间的不匹配决定,并且与连接的发送速率无关。连接在任何时候都有25个数据包在飞行中,但往返时间只有20个数据包到达目的地。如果TCP连接有30个分组窗口,则队列将是10个分组,发送速率没有变化。类似地,如果窗口是20个数据包,则不存在队列,但发送速率是相同的。关于队列大小的发送速率没有任何可以推断出来,除了瞬态突发之外的任何队列只会在网络中造成延迟。发送方需要减少发送中的数据包数量,而不是发送速率。

在上面的例子中,可以看到五个数据包驻留队列仅仅对连接有延迟没有任何好处,因此显然是“坏队列”。如果存在单个瓶颈链接,并且比提供它的链接(比如说,高速以太网链路进入有限的DSL上行链路)要慢得多,那么在瓶颈处可能需要20个缓冲区来临时保持20个数据包在飞行中,以保持瓶颈链路的利用率高。数据包的突发在一个往返时间内将完全清除(01个数据包),这个瞬态队列是“好队列”,因为它允许连接保持20个数据包在发送过程中,并且瓶颈链接被充分利用。在经历的延迟方面,“好队列”大概在一个往返行程中消失,而“坏队列”则会延长一段时间,造成延误。

有效的队列管理能够检测到“好队列”,忽略“坏队列”,并且当检测到坏队列时能够自动采取调整摆脱“坏队列”转化为“好队列”,这就需要一个队列控制器,需要三个基本的组件:

估计机制:弄清楚当前的网络状况。

设定点(阈值):知道好的网络队列的参数,以及坏的网络队列的参数。

控制循环:当检测到当前某个队列是“坏队列”,如何处理,使“坏队列”转化为“好队列”。

下面对上述三个基本组件逐一介绍:

 

2.1 估计机制:

估计器观察到达的所有队列,并检测“好队列”何时变成“坏队列”,反之亦然。Codel在其估计其中有两个创新点:(1)做为队列的指标被观察(2)如何使用观测到的值检测“好/坏队列”。

以前,队列长度被广泛用作观察到拥塞的指标,并且频繁地与发送速率相融合。使用队列长度作为度量对于观察长度的方式和时间很敏感。到达以较低速率服务的缓冲区的高速到达链路可以在经过往返时间之前快速建立一个可能完全分散到单个分组的队列。如果在数据包到达时(如原始RED)或出发时间监视队列长度,则每个数据包将看到一个可能的异常队列。如果队列长度本身是时间采样的(如[REDL1998]中所建议的),可以以相当大的实现复杂性为代价获得队列占用率的更真实的图片。

在可用链路速率的短期和长期变化的网络中(如WiFi中),队列长度的使用进一步复杂化。链路速率下降可能导致队列长度的尖峰,应该被忽略,除非它持续存在。不应该被控制的队列长度,而是由于持久或站立的队列而导致的超出延迟数据包的数量,这意味着缓冲区中的数据包逗留时间正是我们要跟踪的。跟踪缓冲区中的数据包持久时间可以观察每个数据包所经历的实际延迟。休眠时间允许队列管理独立于链路速率,提供使用缓冲区大小的优越性能,并且与用户可见的性能直接相关。无论线路速率更改或多个队列(各个队列可能会以更改速率体验到)的链路共享,它都可以工作。

考虑两个具有不同优先级的队列共享的链接。一旦链路可用,则到达高优先级队列的数据包将被发送,而另一个队列中的数据包必须等到高优先级队列为空(即严格的优先级调度程序)。高优先级队列中的数据包数量可能很大,但是队列快速清空,并且每个数据包花费入队的时间(逗留时间)不大。另一个队列可能具有较少数量的数据包,但分组逗留时间将包括发送高优先级数据包的等待时间。这使得逗留时间成为每个单独队列遇到的拥塞的一个很好的示例。

如何使用观察到的逗留时间将好的队列与坏队列分开?虽然平均值,特别是队列长度,以前已被广泛用作坏队列的指标,但其功效是有问题的。考虑每次往返时间分散的爆发。平均队列将是突发大小的一半,尽管这可能会因计算平均值和到达时间而异。平均队列逗留时间将是清除突发所需的时间。那么平均值将表示一个永久队列。这里不是平均值,建议跟踪最小逗留时间,然后,如果有一个包含一个零逗留时间的数据包,那么就不会有持久队列。当查看队列延迟,检测持久队列中的最小值是很明显的。

可以通过跟踪(本地)最小队列延迟包体验来检测持久性队列。为了确保这个最小值不会过时,最近必须经历,即在适当的过去时间间隔内。该间隔是最小值被认为有效的最大时间量,并且与最大预期爆发消耗所花费的时间量有关。保守地,该间隔应该至少是往返时间,以避免错误地检测持久队列,而不是比往返时间多得多,以避免在检测持久队列时延迟。这表明适当的间隔值是共享缓冲区的所有连接的最大往返时间。

这里有两个创新,Codel估计器的关键模块在于使用逗留时间作为观测值,以及局部最小值作为统计量来监视队列拥塞。本地的最小逗留时间提供一个准确可靠的队列测量,并且使用最小逗留时间具有很大的优势,最小数据包逗留时间能够减小出队列的数据包,这里的意思是Codel机制的所有工作都可以作用于出队列来使其工作。

 

2.2 设置点(阈值):

现在有一个鲁棒的方法来检测站立队列,需要一个设定值来告诉我们何时采取行动。如果控制器设置为在估计器具有非零值时立即采取行动,则平均丢弃率将最大化,这最大限度地减少了TCP的吞吐量。而且,这种策略不会导致随着时间的推移积压(无持久性队列),因为它最大限度地减少了由于分组间隔时间内的正常随机变化引起的瓶颈链路带宽损失。一个最大化利用率的设定点,同时最小化延迟。

如上述分析显示,一个非常小的站立队列使瓶颈链接率达到100.虽然这个结果是针对Reno TCP,但派生仅使用必须适用于任何“TCP友好”传输的属性。已经通过分析和模拟验证,这个结果适用于RenoCubic [TSV84]。这导致设定点的特别简单的形式:允许的站立队列的理想范围在TCP连接的RTT5%到10%之间。因此目标只是2.1节间隔的5%。

 

 

2.3 循环控制:

2.1节描述了一种简单可靠的测量不良(持久)队列的方法。2.2节显示,TCP拥塞控制动态性提供了这一措施的设定值,这在增强吞吐量和最小化延迟之间是一个很好的平衡,并且该设定点是用于区分持久性和相同值的相同“最大平均RTT”间隔的恒定分数暂时队列基本AQM所需的唯一剩余的构建块是一种“控制循环”算法,用于有效地将排队系统从任何“持久队列高于目标”状态驱动到持久队列低于目标的状态。

控制理论为控制回路的设计提供了丰富的方法。大多数经典控制理论处理线性,时间不变,单输入单输出(SISO)系统的控制。这些系统的控制回路通常来自称为比例积分微分(PID)控制器的(很好理解的)类。不幸的是,队列不是线性系统,AQM在最大非线性点(输出链路带宽饱和,因此增加的需求创建延迟而不是更高的利用率)运行。输出队列也不是时不变的,因为流量通常是在任意时间开始和停止的连接的混合,并且可以具有从“开环”UDP音频/视频到“闭环”拥塞的TCP的根本不同的行为。最后,不断变化的连接混合(由于其传递函数差异而不能转换为单个“集总参数”模型)使得系统多输入多输出(MIMO)而不是SISO

由于排队系统不符合经典控制器的先决条件,因此现代状态空间控制器是一种更好的方法,状态为“不持久队列”,“具有持久性队列”。 由于互联网流量混合变化迅速且不可预测,因此噪声和容错适配算法(如随机梯度)是一个不错的选择。由于基本上没有持久队列数量的信息[TSV84],因此适应应该持续多长时间。

考虑流量行为的两个极端,单个开环UDP视频流和单个长时间TCP批量数据传输。如果UDP视频流的平均带宽大于瓶颈链路速率,链路队列将会增长,控制器最终将进入“持久队列”状态并开始丢弃数据包。由于视频流是开环的,所以其到达速率不受影响,所以队列将持续到平均丢失率大于输出带宽赤字(=平均到达率-平均出发率),所以自适应算法的工作是发现这个速度。在这个例子中,适应可以简单地估计到达和离开率,然后以比它们的差异稍大的速度下降。但这种算法根本不适用于批量数据TCP流。TCP以闭环流量平衡运行[TSV84],所以其到达速率几乎总是等于出发率-队列不是速率不平衡的结果,而是TCP发送者的窗口和源目的地之间的不匹配来源往返路径容量(即连接的带宽延迟产品)。发送方的TCP拥塞避免算法将缓慢增加发送窗口(每往返时间一个数据包)[RFC2581],最终会导致瓶颈进入“持久队列”状态。但是,由于平均输入速率与平均输出速率相同,给出视频流的正确丢弃率的速率缺陷估计将计算TCP流的下降率为零。然而,如果输出链路在进入“持久队列”状态时丢弃一个数据包,当发送方发现(通过TCP的正常丢包修复机制)时,它将把窗口减少一倍[RFC2581],所以一轮拖放后的时间,持久队列将消失。

如果存在共享瓶颈的NTCP对话,则控制器必须从每个会话中删除ON)个数据包,从而使所有对话减少其窗口以摆脱持久性队列。如果流量混合包含短路(<=带宽延迟产品)会话,聚合行为变得更像开环视频示例,因为每次会话可能已经发送了所有的数据包,直到它了解一个丢弃的时间 每个下降对后续流量的影响可以忽略不计。

控制器不知道创建队列的会话数量,持续时间或种类,因此必须学习适当的响应。 由于如果多路复用程度(活动对话数量)较小,单滴可能会产生很大的影响,所以以太高的速率下降可能会对吞吐量产生灾难性的影响。以低速率(每个循环次数为1个分组),然后缓慢增加下降速率,直到持续队列低于目标值不太可能过度丢弃,并确保最终消散持久队列。随机梯度学习过程是CoDel控制循环的核心(梯度存在是因为总是减少(瞬时)队列,所以增加的丢弃率总是将系统“向下”移动到无持续队列,而不考虑流量混合)。

使用下降速率与吞吐量的众所周知的非线性关系来获得线性的吞吐量变化,“下一个下降时间”与输入下降状态的滴数的平方根成反比地减少。

由于开始丢弃的最佳速率是每RTT稍多于一个数据包,所以控制器的初始丢弃率可以从第3.1节定义的估计器间隔直接得出。当最小停留时间首先穿过目标并且CoDel丢弃数据包时,控制器可以看到丢弃影响的最早时间是往返时间(间隔)+本地队列等待时间(目标)。如果下一个下降发生在这个时间之前(间隔+目标),CoDel将会过载。在实践中,本地队列等待时间趋于变化,因此使得初始丢弃间隔(即,到第二次丢弃的时间)恰好是最小的可能也导致过度捕获。仿真和实际测量数据分析表明,该变化的第75百分位数值小于目标值,因此初始液滴距离应设置为估计器间隔加上目标的两倍(即初始液滴间距= 1.1 *间隔),以确保控制器已经占据了可接受的拥塞延迟。

使用最小统计量可以将控制器置于估计器的出队例程中。这意味着控制信号(下降)可以在不良队列的第一个符号(由逗留时间指示)发送,并且一旦停留时间低于设定值,控制器就可以停止工作。

 

网络边缘的队列管理方案:

CoDel最初被设计为消费者网络边缘的缓冲区解决方案。 CoDel构建块能够适应不同或时变链路速率,易于与多个队列一起使用,具有良好的利用率和低延迟,并且实现简单有效。CoDel需要的唯一设置是它的间隔值,100ms满足普通互联网使用的定义,CoDel可以免参与使用。CoDel被发布到开源社区,在那里已被广泛公布并适应许多问题。CoDel的高效实施和缺乏配置是独特的功能,使其适合于管理现代数据包缓冲区。

 

3.1 Codel 动态队列管理概述:

为确保链路利用率不会受到不利影响,CoDel的估计器将其目标设置为优化功率的设定值,CoDel的控制器不会丢弃数据包,当丢弃将队列置空或使用少于最大传输单元(MTU)的字节数 在缓冲区。2.2节显示理想设定值为连接RTT5-10%。在开放的互联网中,特别是在消费者边缘预计大多数未分类的RTT的上限为100ms。 使用此RTT给出了5ms的最小目标,跟踪最小值的间隔为100ms。 实际上,不合格的链接在RTT上会比不定期的停留时间低于目标,所以估计器对于间隔的值不会过于敏感。

当估计器发现持续延迟高于目标时,控制器进入丢弃数据包的丢弃状态,并设置下一个丢弃时间。如第2.3节所述,初始下一个下降间距应足够长,以使端点有时间对单个引脚进行反应,因此应该设置为1.1倍的间隔值。如果估计器的输出低于目标值,则控制器取消下一个下降并退出下降状态。(控制器比估计器更敏感到过短的间隔,因为会发生不必要的丢弃,链路利用率降低)。如果在控制器仍处于丢弃状态下达到下一个丢弃时间,则出队的数据包将被丢弃, 重新计算下一个下降时间。 额外的逻辑防止在退出之后重新进入丢弃状态,并在最近的控制级恢复丢弃状态(如果存在)。

CoDel AQM只有当本地最小停留延迟超过目标时,要进入其丢弃状态,必须持续一段足够长的时间间隔都检测到最小逗留时间超过目标值时,以防止正常的突发消失,确保适合管道的数据包突发不会丢失。

3.2 非饥饿:

CoDel的目标是控制延迟,对链路利用率没有甚至没有影响,并且部署在包括可变速率链路在内的各种链路带宽上,而无需重新配置。为了防止在输出链路饿死时,CoDel进行另一个检查,然后再丢弃,以查看缓冲区中是否至少有一个MTU值的字节。如果没有,则该数据包不应该被丢弃,并且当前CoDel退出丢弃状态。MTU大小可以自适应地设置到目前为止看到的最大数据包,或者可以从驱动程序读取。

3.3 间隔值的使用

选择该间隔以给出端点对时间作出反应的时间,而不会使得响应时间受到影响。 CoDel的估计器,设定值和控制回路都使用间隔。了解它们的推导结果表明,CoDel对单个长寿命TCP的间隔值最敏感,流量混合的灵敏度降低。这是幸运的,因为RTT在连接之间有所不同,并不为人所知。最好的策略是使用一个比使用链接大多数连接所看到的RTT略大的间隔,一个值可以被确定为所看到的最大RTT,如果该值不是离群值(使用第95-99位值)应该工作)。100ms的间隔设置在10ms1秒的RTT范围内工作良好(在10个范围内实现了优异的性能对于用于正常地面互联网的设备,间隔应该具有100ms的值,这只会导致超长时间TCP长时间超过100msRTT,并且与其他连接的混合很少链接。

3.4 目标值的设定:

目标是最大可接受的持续队列延迟,CoDel正在丢弃或准备下降,CoDel不在其下方。2.2节的计算结果表明,最佳设定值为RTT5-10%,低端为5%。使用模拟来探讨TCP与其他流量和不同RTT的连接混合时的影响。因此,广泛地尝试了RTT范围的5-10%的值,总的来说,使用30500msRTT120毫秒之间的目标值和64Kbps100Mbps的链路带宽,以实验性地探索给出一致的设定值同时控制带宽,RTT和流量负载范围内的延迟。结果与2.2节的数学特别一致。低于5ms的目标,利用率受到一些条件和交通负荷的影响,而在5ms以上,看到的利用率很少或没有改善。因此,正常互联网流量应该设置为5ms

拥有(但不是过载)的CoDel链路与仅由主要由长寿命的TCP流组成的流量将具有通过该链路的中值延迟将趋向于目标。 对于突发业务负载和过载条件(所有到达流都难以或不可能适应),中间队列将比目标长。

逗留时间必须保持在目标上方一整个间隔以便进入丢弃状态。任何逗留时间小于目标的数据包将重置队列在目标下方的时间。由于互联网流量具有非常动态的特征,因此数据包经历的实际滞后延迟差异很大,往往小于目标,除非过载过大。当一个链接没有超载时,它不是一个瓶颈,并且分组的逗留时间会很小或者不存在。在通常的情况下,沿路径只有一个或两个位置,其中数据包将遇到瓶颈(通常在边缘),所以即使在极度拥塞的条件下,数据包所经历的排队延迟的总量也应小于10ms

4.5 在多个队列中的使用

与其他AQM不同,CoDel可轻松适应多个队列系统,使用其他方法,总是存在如何解决每个队列随时间接收小于全部链路速率的事实的问题,并且通常会看到随时间变化的速率。这正是CoDel擅长的:在缓冲区中使用数据包的逗留时间完全可以避免这个问题。在多队列设置中,单独的CoDel算法在每个队列上运行,但每个CoDel实例使用数据包逗留时间与单队列CoDel相同。正如一个单队列CoDel适应变化的链路带宽,多队列CoDel系统也是如此。作为优化以避免排队超出必要的,在测试队列占用之前,应该使用共享相同输出链路的所有队列的总占用率。CoDel的这个属性已经在fq_codel中被利用。

4.6 设置:

CoDel可用于开放式互联网中的设备。使用100ms的间隔,目标设置为间隔的5%,并且初始间距也设置为间隔。已经选择了这些设置,使得可以出售诸如小型WiFi路由器的设备,而不需要使任何值被调整,从而产生无参数的实现。此外,CoDel在与正常Internet具有明显不同特征的环境中非常有用,例如在数据中心内用作集群互连的交换机中。由于群集流量完全是数据中心内部的,所以往返延迟较低(通常<100us),但带宽较高(1-40Gbps),因此分布式计算的聚合阶段相对容易(例如,映射/缩小)持续填充,然后溢出大多数高速开关中可用的适度的perport缓冲区。

现在Codel不仅仅作为Linux动态队列的一种方案,这种设计思想还被很多的动态队列借鉴,比如fq_codel队列管理方案,商业中现在的Google数据中心也采用这种方案,并且效果较为明显。

1 0