聊聊我们使用的QoS

经常有人跑过来问,我们线上(线下)的端口带宽设置是多少啊? 我通过外网端口端口走的和通过L3走的带宽有什么不同吗? 我的带宽是否自己独享?

说到QoS, 相信很多人可以随口说出一堆的概念来,什么令牌桶啦,色盲模式啦,单速率/双速率啦,差分服务啦等等。本文并不想解释这么多高深的概念,只想尽可能的把我们当前使用的这一套QoS机制给大家解释清楚。拿高速公路的例子来做个类比:

大家都知道,高速公路上有双向4车道,双向8车道甚至双向10车道。一般来说,车道越多,你开车的速度就可以越快。这里的车道数量,在QoS的世界里,其实就是带宽;而车速就是报文传输速率;高速公路上一辆辆的车就可以认为是一个个长短不一的报文。高速公路上一般都会设置监控探头,用来测速,监控流量,这个概念同样的也可以作用于QoS。一旦路上发生了车祸导致某个路段发生了拥塞,交警蜀黍一般都在高速入口处告知,嘿,哥们,前方20km公里处严重拥挤,您换道吧,这在QoS中可以认为是流量监管和拥塞避免(tail drop)。那么,一旦发生了事故,救护车要过来该怎么办呢?QoS中有一种说法叫流量分类和标记,救护车的优先级肯定是最高,走绿色通道(硬路肩),其他车旁边让路。在车道无法增加的情况下,我们怎么才能提高车速呢?想一下,如果路上大部分是公共交通汽车,只有少量的私家车,假设一辆大巴上可以坐50人,那么分散到一个5座轿车上就需要10辆。而这辆车里只要有一辆速度慢,那么整个的车速就降下来了。所以大力提倡公共交通,不仅可以提高城市环境质量,还提高出行质量。体现在QoS的世界里,其实道理是一样的,一次发送的报文长度越长,带宽的利用率就越高。

前面的例子里提到了几个概念,带宽,优先级。 

先来看看带宽,衡量带宽的单位通常是bps(bit per second),也有拿pps(packet per second)来衡量的,这两个单位之间的换算关系如下:

bps = pps * packet_length * 8

pps = bps / 8 / packet_length

通常我们说pps的时候,是以最小报文长度来衡量的,比如linux系统发出的最小报文长度是64; 而通常我们说bps的时候,是以ethernet payload >=1500来衡量的

来看看优先级。 通常我们提到QoS的时候,会以上层业务来区分优先级,比如ftp数据传输服务需要的可能只是数据的完整性,对时延相对不敏感的可以放到低优先级;而对于语音之类的业务对时延要求比较高的优先级调的高一点。 在我们云计算平台的QoS中虽然也使用了优先级的概念,不过稍微有点不同,低速率的报文优先级高,而高速率的报文优先级低,这就是大家经常能听到的保证速率和最大速率。 以下这张图简单显示了我们QoS的架构:

从上图我们可以很清楚的看到, 从虚拟机出来的报文被分成了3种类型, 绿颜色标记的是最高优先级,就是我们通常所说的保证速率; 蓝颜色标记的报文优先级次之,这两类报文都是能通过虚拟机网卡出去的;而红颜色标记的报文就没那么幸运了,直接出不了虚拟机的tap网卡就会被丢掉,这类报文的速率大于我们设置的最大速率。 那么我们是怎么来保证低速率的报文优先通过呢? 看上图的虚线方框,所有的虚拟机报文出来后最终要通过物理网卡出去,我们在虚拟机的报文出来的时候做了一下标记,这个标记最终会被带到物理网卡,而在物理网卡上我们使能了一个优先级队列,这个队列总共有3个不同的优先级,通过命令行tc qdisc show dev eth0,我们能看到这样的结果:

这里的bands 3就是表明有3个不同的队列,prio表示是优先级队列。(如果什么都没配置,显示的应该是默认的pfifo_fast)

从图上我们可以得到另外两个结论: 第一,我们的QoS架构设计里只有policing没有shaping; 第二,同样优先级的报文进入物理网卡后就是FIFO了,也就是说同优先级的报文是存在共享关系的,有个先来后到,如果带宽真的已经超售,那么就算所有虚拟机发出的报文都在保证速率以内,还是有可能会被丢弃,不过丢弃它的就不是虚拟机的tap网卡,而是物理网卡了。 到这里我们可以回答其中一个问题了,租户带宽是否独享? 答案是否定的,不管租户走的是私网还是公网,带宽都是和在同一宿主机上的其他租户的虚拟机共享。


解释一下mpu的概念。前面我们已经说过,一次发送的报文长度越长,带宽的利用率就越高。还记得前面pps和bps的关系吧,那么就可以这么解释,在同样的带宽下,报文长度越小,每秒钟发送的报文就越多,也就是宿主机需要处理的报文越多,而宿主机的能力是有上限的,因此,为了解决小报文攻击引起的宿主机负载过高,我们引入了mpu(minimum packet unit)最小报文长度。 这个是虚拟机网卡队列的一个属性, 引入该属性后,我们对于特定的pps和bps,计算出一个最小报文长度,一旦虚拟机发出的报文小于这个长度,那么qos统计的时候就会以这个值作为报文长度(当然实际发出去的报文长度是不会变的)。 举个例子,在当前我们的默认设置500Mbps和50Kpps下,计算出来的mpu是1280B。因此,如果发出的报文是64B, 理论上我们能发出每秒10,000,000个报文,而实际确只能发出50,000个报文,这当然就很大程度上减轻了宿主机的压力。

接下来解释一下最近遇到的公有云虚拟机获取不到外网ip的坑是怎么被踩出来的。估计某些测试人员还有印象,有虚拟机被当成肉鸡,以虚拟机网卡的线速能力发出了广播报文,这些广播报文在二层网络内游荡,导致租户的虚拟机忙于应付这类无效报文。为了解决这个问题,我们在虚拟机出口的qos上做了广播报文限速,规定每秒不得发出超过10个报文。 当时我们是以每秒能发出的最大ARP报文数作为参考值来计算的,对于burst我们以报文最大能延迟500ms来计算。 在500Mbps的时候,队列显示如下:

而在蜂巢公有云上,默认的外网带宽是1Mbps,按照10pps计算出来的结果:

获取外网ip的时候,我们需要发送dhcp request报文,该报文是一个广播报文,根据我们在虚拟机中dhclient的设置,需要带一堆option,最终出来的dhcp报文长度为342字节。而在带宽设置为1Mbps的时候,一次burst的值才320字节,还不够发出一个报文的,此时我们如果用命令tc -s filter show dev tapxxx parent ffff: 就能看到dhcp 报文每出一个,报文就丢一个。 所以在修改的代码没有上线前,我们通过手工调整用户带宽的方式也能使其获取到ip地址,就是这个道理。(为了解决这个问题,我们后续对于广播报文不仅将mpu的值调大,而且将其最大延时时间也增大了)

最后总结一下,并回答开头提出所有的问题:

1.租户的带宽不是独享的,和其他在同一宿主机上的虚拟机共享带宽

2.L3 router是每个租户一个,路由器的带宽上下行带宽设置是一样的,但是区分内网和外网。默人情况下,内网带宽100Mbps,外网带宽10Mbps。 该值现在可通过API设置。

 (注: 用户使用vpn的时候需要通过l3连接,走的是内网通道,因此尽量不要通过vpn来传递很大的数据)

3.私有网和机房网带宽,默认都是保证速率50Mbps,最大速率500Mbps。公有云的外网端口带宽用户在前端界面可配置,最大100Mbps。虚拟机端口的带宽也区分上行和下行。

 egress方向(上行,从虚拟机访问外网)的带宽是用户配置的,而ingress方向(下行,从外网访问虚拟机)的带宽根据egress来决定,如果egress的带宽小于80Mbps, 则ingress的带宽为80Mbps; 如果egress带宽大于80Mbps,则ingress带宽等于egress带宽。

  注:现在我们下行方向不参与计费,只有从虚拟机出去的流量才参与计费

4.广播报文默认的pps是10, 而其他所有的报文默认pps为50K。 由于我们的mpu是会随着pps和bps而改变,那些需要更大pps的人请根据自己实际业务需要,估算报文平均长度后,自己设置合理的pps和bps,单独调整某个值可能会没有效果哦。 我们已经提供了API来调整这两个pps的值。

5.qos是否使能可以按节点控制,最小粒度是端口。

网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者陈跃芳授权发布。