[Linux 常用技巧] 使用 linux 下的 TC 进行服务器流量控制
转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]
本文链接: http://www.php-oa.com/2009/06/23/linux_tc.html
公司一台服务器,网络环境太高,那台服务器和源服务器连接下载,就跑到400M-500M,为了控制一下,所以研究了一下TC.来做流量控制.给他控制到小点,不要让这一台占了所有的网络.TC很是强大啊,很多所谓的硬件路由器,都是基于这个做的.
TC介绍
在 linux 中,TC 有二种控制方法 CBQ 和 HTB.HTB 是设计用来替换 CBQ 的.它是一个层次式的过滤框架.
TC包括三个基本的构成块:
队列规定 qdisc(queueing discipline )、类(class)和分类器(Classifiers)
TC 中的队列(queueing discipline):
用来实现控制网络的收发速度.通过队列,linux可以将网络数据包缓存起来,然后根据用户的设置,在尽量不中断连接(如 TCP)的前提下来平滑网络流量.需要注意的是,linux对接收队列的控制不够好,所以我们一般只用发送队列,即“控发不控收”.它封装了其他两个主要 TC组件(类和分类器).内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的qdisc(排队规则)把数据包加入队列.然后,内核会尽可能多地从qdisc里面取出数据包,把它们交给网络适配器驱动模块.
最简单的 QDisc 是 pfifo 它不对进入的数据包做任何的处理,数据包采用先入先出的方式通过队列.不过,它会保存网络接口一时无法处理的数据包.
队列规则包括FIFO(先进先出),RED(随机早期探测),SFQ(随机公平队列)和令牌桶(Token Bucket),类基队列(CBQ),CBQ 是一种超级队列,即它能够包含其它队列(甚至其它CBQ).
TC 中的 Class 类
class 用来表示控制策略.很显然,很多时候,我们很可能要对不同的IP实行不同的流量控制策略,这时候我们就得用不同的class来表示不同的控制策略了.
TC 中的 Filter 规则
filter 用来将用户划入到具体的控制策略中(即不同的 class 中).比如,现在,我们想对xxa,xxb两个IP实行不同的控制策略(A,B),这时,我们可用 filter 将 xxa 划入到控制策略 A,将 xxb 划入到控制策略 B,filter 划分的标志位可用 u32 打标功能或 IPtables 的 set-mark (大多使用iptables 来做标记)功能来实现.
目前,TC可以使用的过滤器有:fwmark分类器,u32 分类器,基于路由的分类器和 RSVP 分类器(分别用于IPV6、IPV4)等;其中,fwmark 分类器允许我们使用 Linux netfilter 代码选择流量,而 u32 分类器允许我们选择基于 ANY 头的流量 .需要注意的是,filter (过滤器)是在QDisc 内部,它们不能作为主体.
TC 的应用流程
数据包->iptables(在通过iptables时,iptables根据不同的ip来设置不同的mark)->TC(class)->TC(queue)
应用
假设 eth0 位是服务器的外网网络接口.
开始之前,先要清除 eth0所有队列规则
tc qdisc del dev eth0 root 2> /dev/null > /dev/null
1) 定义最顶层(根)队列规则,并指定 default 类别编号
tc qdisc add dev eth0 root handle 1: htb default 2
2) 定义第一层的 1:1 类别 (速度)
本来是要多定义第二层叶类别,但目前来看,这个应用中就可以了.
tc class add dev eth0 parent 1:1 classid 1:2 htb rate 98mbit ceil 100mbit prio 2 tc class add dev eth0 parent 1:1 classid 1:3 htb rate 1mbit ceil 2mbit prio 2
注:以上就是我们控制输出服务器的速度,一个为98M,一个为 2M.
rate: 是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类.
prio:用来指示借用带宽时的竞争力,prio越小,优先级越高,竞争力越强.
ceil: ceil是一个类最大能得到的带宽值.
同时为了不使一个会话永占带宽,添加随即公平队列sfq.
tc qdisc add dev eth0 parent 1:2 handle 2: sfq perturb 10 tc qdisc add dev eth0 parent 1:3 handle 3: sfq perturb 10
3) 设定过滤器
过滤器可以使用本身的 u32 也可以使用 iptables 来打上标记
指定在root 类 1:0 中,对 192..168.0.2 的过滤,使用 1:2 的规则,来给他 98M 的速度,写法就如下
tc filter add dev eth0 protocol ip parent 1:0 u32 match ip src 192.168.0.2 flowid 1:2 tc filter add dev eth0 protocol ip parent 1:0 u32 match ip src 192.168.0.1 flowid 1:3
如果是所有 ip 写法就如
tc filter add dev eth0 protocol ip parent 1: prio 50 u32 match ip dst 0.0.0.0/0 flowid 1:10
使用 Iptables 来配合过滤器
还可以使用这个方法,但需要借助下面的 iptables 的命令来做标记了
tc filter add dev eth0 parent 1: protocol ip prio 1 handle 2 fw flowid 1:2 tc filter add dev eth0 parent 1: protocol ip prio 1 handle 2 fw flowid 1:3
iptables 只要打上记号就行了
iptables -t mangle -A POSTROUTING -d 192.168.0.2 -j MARK --set-mark 10 iptables -t mangle -A POSTROUTING -d 192.168.0.3 -j MARK --set-mark 20
TC对最对高速度的控制
Rate ceiling 速率限度
参数ceil指定了一个类可以用的最大带宽, 用来限制类可以借用多少带宽.缺省的ceil是和速率一样
这个特性对于ISP是很有用的, 因为他们一般限制被服务的用户的总量即使其他用户没有请求服务.(ISPS 很想用户付更多的钱得到更好的服务) ,注根类是不允许被借用的, 所以没有指定ceil
注: ceil的数值应该至少和它所在的类的速率一样高, 也就是说ceil应该至少和它的任何一个子类一样高
Burst 突发
网络硬件只能在一个时间发送一个包这仅仅取决于一个硬件的速率. 链路共享软件可以利用这个能力动态产生多个连接运行在不同的速度. 所以速率和ceil不是一个即时度量只是一个在一个时间里发送包的平均值. 实际的情况是怎样使一个流量很小的类在某个时间类以最大的速率提供给其他类. burst 和cburst 参数控制多少数据可以以硬件最大的速度不费力的发送给需要的其他类.
如果cburst 小于一个理论上的数据包他形成的突发不会超过ceil 速率, 同样的方法TBF的最高速率也是这样.
你可能会问, 为什么需要bursts . 因为它可以很容易的提高向应速度在一个很拥挤的链路上. 比如WWW 流量是突发的. 你访问主页. 突发的获得并阅读. 在空闲的时间burst将再"charge"一次.
注: burst 和cburst至少要和其子类的值一样大.
TC命令格式:
加入
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
查看TC的状态
tc -s -d qdisc show dev eth0
tc -s -d class show dev eth0
删除tc规则
tc qdisc del dev eth0 root
实例
使用 TC 下载限制单个IP 进行速度控制
tc qdisc add dev eth0 root handle 1: htb r2q 1 tc class add dev eth0 parent 1: classid 1:1 htb rate 30mbit ceil 60mbit tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.1.2 flowid 1:1
就可以限制192.168.1.2的下载速度为30Mbit最高可以60Mbit ,其中 r2q,是指没有default的root,使整个网络的带宽没有限制
使用 TC 对整段 IP 进行速度控制
tc qdisc add dev eth0 root handle 1: htb r2q 1 tc class add dev eth0 parent 1: classid 1:1 htb rate 50mbit ceil 1000mbit tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.111.0/24 flowid 1:1
就可以限制192.168.111.0 到255 的带宽为3000k了,实际下载速度为200k左右.
这种情况下,这个网段所有机器共享这200k的带宽.
还可以加入一个sfq(随机公平队列)
tc qdisc add dev eth0 root handle 1: htb r2q 1 tc class add dev eth0 parent 1: classid 1:1 htb rate 3000kbit burst 10k tc qdisc add dev eth0 parent 1:1 handle 10: sfq perturb 10 tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.111.168 flowid 1:1
sfq,他可以防止一个段内的一个ip占用整个带宽.
使用 TC 控制服务器对外的速度为 10M
如下,我要管理一台服务器,只能向外发 10M 的数据
tc qdisc del dev eth0 root tc qdisc add dev eth0 root handle 1: htb tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit ceil 10mbit tc qdisc add dev eth0 parent 1:10 sfq perturb 10 tc filter add dev eth0 protocol ip parent 1: prio 2 u32 match ip dst 220.181.xxx.xx/32 flowid 1:1 # 上面这台,让 220.181.xxx.xx/32 这台跑默认的,主要是为了让这个 ip 连接进来不被控制 tc filter add dev eth0 protocol ip parent 1: prio 50 u32 match ip dst 0.0.0.0/0 flowid 1:10 # 默认让所有的流量都从这个通过
参考:http://blog.chinaunix.net/u3/94771/showart_1906064.html
http://liuleijsjx.javaeye.com/blog/402152



















大牛。我都没有机会接触到这个。。
我想把带宽限制到200M ,下面的命令执行了,自己都登陆不上了
tc qdisc add dev eth0 root tbf rate 200kbit latency 200ms burst 1000
请问每个连接限速200K,总共限制在200M,然后最大1000个连接,上面的写法对吗。大哥
TC流量控制的文章真少啊,收藏!
正在研究这个TC流量控制,请多多指教
panabit 这个软件也不错,我用来做公司网关,限制流量,大概一年多了都没重启过,很稳定。
你那是一个软件,tc 是内核的一个组件
收藏!TC流量控制
对所有进入服务器的所有IP进行限制
tc qdisc add dev eth0 root handle 1: htb r2q 1
tc class add dev eth0 parent 1: classid 1:1 htb rate 30mbit ceil 60mbit
tc filter add dev eth0 parent 1: protocol ip prio 16 u32 match ip dst 192.168.1.2 flowid 1:1
第三行这个要怎么改?(想把192.168.1.2换成所有的IP)谢谢