1. qdisc(排队规则)、class(类别)和filter(过滤器)
Linux操作系统中的流量控制器TC(TrafficControl)用于Linux内核的流量控制,它利用队列规定建立处理数据包的队列,并定义队列中的数据包被发送的方式,从而实现对流量的控制。
- qdisc通过队列将数据包缓存起来,用来控制网络收发的速度
- class用来表示分类策略
- filter用来将数据包划分到具体的分类中
1.1 队列
TC模块实现流量控制功能使用的队列规定分为两类:
-
一类是无类队列规定
无类队列对进入网络设备(网卡)的数据流不加区分统一对待的队列
这类队列规定形成的队列可以对整个网络设备(网卡)的流量进行整形,但不能细分各种情况。
这类队列规定使用的流量整形手段主要是排序、限速和丢包。
常用的无类队列规定主要有pfifo_fast(先进现出)、TBF(令牌桶过滤器)、SFQ(随机公平队列)、ID(前向随机丢包)等等。 -
另一类是分类队列规定
分类队列对进入网络设备的数据包根据不同的需求以分类的方式区分对待的队列规定。
数据包进入一个分类的队列后,它就需要被送到某一个类中,也就是说需要对数据包做分类处理。
对数据包进行分类的工具是过滤器,过滤器会返回一个决定,队列规定就根据这个决定把数据包送入相应的类进行排队。每个子类都可以再次使用它们的过滤器进行进一步的分类。直到不需要进一步分类时,数据包才进入该类包含的队列排队。
除了能够包含其它队列规定之外,绝大多数分类的队列规定还能够对流量进行整形。这对于需要同时进行调度(如使用SFQ)和流量控制的场合非常有用。
1.2 控制策略
流量控制包括以下4种方式
- SHAPING(限制)
当流量被限制,它的传输速率就被控制在某个值以下。限制值可以大大小于有效带宽,这样可以平滑突发数据流量,使网络更为稳定。shaping(限制)只适用于向外的流量。 - SCHEDULING(调度)
通过调度数据包的传输,可以在带宽范围内,按照优先级分配带宽。SCHEDULING(调度)也只适于向外的流量。 - POLICING(策略)
SHAPING用于处理向外的流量,而POLICIING(策略)用于处理接收到的数据。 - DROPPING(丢弃)
如果流量超过某个设定的带宽,就丢弃数据包,不管是向内还是向外。
2. TC命令操作
2.1 tc命令
tc可以使用以下命令对QDisc、类和过滤器进行操作:
tc qdisc [ add | change | replace | link ] dev DEV [ parent qdisc-id | root ] [ handle qdisc-id ] qdisc [ qdisc specific parameters ]
tc class [ add | change | replace ] dev DEV parent qdisc-id [ classid class-id ] qdisc [ qdisc specific parameters ]
tc filter [ add | change | replace ] dev DEV [ parent qdisc-id | root ] protocol protocol prio priority filtertype [ filtertype specific parameters ] flowid flow-id
tc [-s | -d ] qdisc show [ dev DEV ]
tc [-s | -d ] class show dev DEV tc filter show dev DEV
2.2 基本步骤
- 针对网络物理设备(如以太网卡eth0)绑定一个队列QDisc;
- 在该队列上建立分类class;
- 为每一分类建立一个基于路由的过滤器filter;
- 最后与过滤器相配合,建立特定的路由表。
3. 流控算法
3.1 漏桶(Leaky Bucket)算法
水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),
当水流入速度过大会直接溢出(访问频率超过接口响应速率), 然后就拒绝请求,
漏桶算法有两个变量:
一个是桶的大小,支持流量突发增多时可以存多少的水(burst),
另一个是水桶漏洞的大小(rate)。
3.2 令牌桶算法(Token Bucket)
随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)
往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水)
如果桶已经满了就不再加了. 新请求来临时
会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.
3.3 漏桶算法与令牌桶算法的区别
- 漏桶算法能够强行限制数据的传输速率
- 令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输
4. 云环境下的动态流控
传统的流控采用的是静态预分配。
而在云计算环境下,服务节点也会由于服务的动态上下线而处于频繁变化的状态,这种场景下静态分配显然没办法满足需求。
云服务的资源也是动态分配的,静态分配阈值的方法没办法迁移到云上
4.1 方案一:动态流控
以服务注册中心以流控周期T为单位,动态推送每个节点分配的流控阈值QPS,当服务节点发生变更时,会触发服务注册中心重新计算每个节点的配额,然后进行推送,这样无论是新增还是减少服务节点,都可以在下一个流控周期内被识别和处理,实现动态变更
4.2 方案二:配额动态申请和返还
每个节点根据自己分配到的值和自身处理速率做出预测,若指标有剩余就返还给注册中心,若不够,就主动像注册中心申请,申请不到配额时就做出节流限制