大神带你读懂HCIE-Routing & Switching面试之调度

上一篇关于服务质量QoS文章中,我们讲到了报文分类和标记,这篇文章让我们再来了解一下调度机制。

上文中,我们的语音、视频、数据这三份流量进入到了各自的队列中,然后我们需要对其进行调度。调度怎么理解呢?就是如何安排进来的流量有秩序有主次地出去。调度分为两种:

① 基于队列的调度: 内部是虚拟出了7个队列。假如语音进入了队列5、视频队列4、数据队列3. 基于队列的调度它是怎么工作的呢?

首先基于队列的调度分RR(轮询)——WRR(加权轮询)——WFQ(加权公平)——PQ(按优先级出流量)

很明显语音(队列5)>视频>数据,则RR就语音走一个包,视频走一个包,数据走一个包,然后循环 RR。虽说非常公平,但我们要的是区别对待,高优先级先走,低优先级排后面。所以又开发了WRR,我们给语音队列加一个权重值3、视频2、数据不给,这样每一个循环语音就走3个包,视频走2个 数据还是走1个,这样就解决高优先级先溜的问题。不过还有一个问题,现实中,我们通常是以带宽来衡量的,假如数据的一个包1500字节,语音1个包100个字节,那么这样的一个循环,数据反而占用的带宽更高。

所以又开发了WFQ,加权又公平,基于带宽来分配,语音分30M、视频分20M、数据分10M,这样就解决了上述问题。

那么PQ是什么,PQ就像一个莽夫,往前冲就对了。语音优先级高,那我就先把语音的流量走完,再走视频再走数据。这样虽然高优先级的很开心,但如果语音一直有流量,那么视频、数据就一个包都发不出了,会造成低优先级流量饿死的情况,显然也是不可取的。

不过一般而言,现实中一般会采用结合的方式比如PQ+WRR,PQ+WFQ这种方式。

讲完基于队列的调度,接下来讲讲基于类的调度。

② Class Based Queueing(CBQ)基于类的加权公平队列是对WFQ功能的扩展, 为用户提供了定义类的支持。CBQ首先根据IP优先级或者DSCP优先级、输入接口、IP报文的五元组等规则来对报文进行分类,然后让不同类别的报文进入不同的队列。对于不匹配任何类别的报文,送入系统定义的缺省类。

那CBQ提供了哪几个队列呢?

EF队列:满足低时延业务
AF队列:满足需要带宽保证的关键数据业务
BE队列:满足不需要严格QoS保证的尽力发送业务

我们现在通过简单流分类or复杂流分类将语音分成一类,视频分成一类,微信数据分成一类,发语音的时候,我们应该会对时延有着很高的要求,视频则较高,发微信呢,卡个1-2s也还能接受,所以我们会将语音类流量,送入EF队列,视频类流量送入AF队列,剩下的微信流量就默认就进入我们的BE队列。

在EF队列中采用PQ调度,在AF队列中采用WFQ,在BE采用WFQ,所以我们会为EF队列设置一个最大带宽限制(毕竟用PQ免得BE的流量饿死了) ;为AF队列设置一个最小带宽限制,剩下的带宽给BE用。在EF中还有一个特殊的队列LLQ, LLQ比EF更优。

这样我们就调度完了,接下来是不是该出去了?我们可以在出接口的地方做流量管理。讲流量管理前我们再想想,假如流量真的很多,我再怎么调度,所有队列都满了,但是入口还一直进来流量,这个时候怎么办?会发生拥塞对吧?堵住了,难进,出去又慢。这个时候我们就要讲一讲发生拥塞时候的拥塞避免。

拥塞避免

当我们拥塞时,队列满了会造成什么问题呢?尾丢弃,就是后面进来的流量直接就丢包了。所以尾丢弃会造成3个问题:1、不加分区丢包;2、TCP全局同步;3、TCP流量饿死。接下来我们来进入TCP的领域。

TCP是一个可靠安全的传输协议,有确定机制,丢包会重传等。假如TCP丢包了,等待重传计时器超时,然后重传,称超时重传;假如TCP丢了一部分的包,接收方能够通过序列号等参数,确定你发来的数据不完整,这时接收方会立刻连续重复发三个ACK报文,发送方立刻意识到接收方刚刚没收完整我发的包,立刻重发,称快重传。

接下来我们来看看在网络中,我们的TCP如何启动并且发送数据的(TCP的一个窗口)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kxhbpmp8-1584326588689)(http://www.tklab.cn/uploadfile/2020/0312/20200312095904755.jpg)]

我们来看一下这个图,并解释一些名词:

拥塞窗口cwnd是发送方为一个动态变化的窗口叫拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度。

ssthresh是慢启动门限(这里我们设置成16)cwnd=24时为阈值(默认是56636B);

慢开始也称慢启动,是指建立TCP连接时,把cwnd设置=1(536B)然后进行一个指数增长。

接下来进入重点:

现在有一个TCP连接——>开始一个慢启动从cwnd=1开始指数增长到cwnd=16时候到达门限了,开始拥塞避免,就进入一个加法增长(发送的报文如果都收到ACK回复,cwnd会加法性的+1+1+1)——>到达cwnd=24阈值时检测到了拥塞——>立即把ssthresh门限降为阈值的一半也就是12,即新的ssthresh=12,为上图的②+③。接来下有两种处理行为:

① 拥塞后如果是超时重传造成的丢包,则cwnd=1,此时的ssthresh则为12,为上图的④+⑤

② 拥塞后如果是快重传造成的丢包,则cwnd=12,进行一个拥塞避免,为上图的①

大家捋清楚上图后,接下来TCP全局同步是什么意思呢?上图是一个TCP连接,假如有100个N个TCP连接用时进行,那么这100个TCP连接同时到达阈值,把阈值下降一半,会造成带宽的浪费;如果50个先到阈值,下降一半,再慢启动,另外50个就可以利用之前50个的带宽。

那TCP流量饿死又是什么呢?TCP流量饿死是指当TCP在cwnd很小时,如果UDP流量大量持续进来,就会造成TCP的cwnd一直很小,最后TCP流量无法传出则称饿死。

那我们怎么解决这些拥塞造成的问题呢?在我们拥塞避免的阶段,我们用一个叫做wred(加权早期随机检测)的技术,这个技术是我们为每一个队列配置一个丢弃模板,在队列还没满时,高优先级的丢10个包,低优先级丢20个包,这样处理,有效解决了TCP全局同步+TCP流量饿死+不加区分的丢包。