tc限速必须作用于egress方向且仅对真实网卡生效:它只控制本机发出的出向流量,无法直接限制入向流量;若需限下载速度,须借助ifb虚拟设备将ingress流量重定向至ifb0的egress路径再限速;规则必须绑定eth0等物理接口,lo、docker0、veth等虚拟接口无效。

tc限速必须作用于egress方向,且只对真实网卡生效
Linux的tc命令只能控制**出向流量(egress)**,也就是本机发出的数据包。它不处理入向(ingress)流量——想限下载速度,不能直接在eth0上做,得靠ifb虚拟设备或应用层配合。所有规则必须绑定到物理网卡(如eth0、ens33),对lo、docker0、veth*等虚拟接口直接加root限速无效(容器场景需用clsact+cgroup2)。操作前务必确认:用ip link show查网卡状态是否UP;用tc qdisc show dev eth0看是否有残留规则;所有命令需sudo权限。
用htb建分层结构实现带宽保障+限制
单纯限速容易导致服务卡顿,真正可用的方案是用htb设最小保障(rate)和最大上限(ceil)。比如保障SSH(22端口)始终有512kbit,但最多不超2mbit:
sudo tc qdisc add dev eth0 root handle 1: htb default 30<br>sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit<br>sudo tc class add dev eth0 parent 1:1 classid 1:2 htb rate 512kbit ceil 2mbit prio 1<br>sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 22 0xffff flowid 1:2
-
rate是保证带宽,即使其他流量空闲,该类也能独占这部分 -
ceil是突发上限,仅当总带宽有余时才可突破rate - 没匹配到的流量走
default 30,对应classid 1:30,需提前创建 - 多个
class间按prio值排队,数值越小优先级越高
按IP/端口匹配流量时,filter中的src/dst含义易混淆
在egress规则里:match ip src指的是**本机IP**,match ip dst才是远端目标IP。例如限制本机发给192.168.1.100的流量,必须写match ip dst 192.168.1.100;若想限“来自192.168.1.100的请求”的响应速度,实际是限本机回给它的包,仍用dst匹配那个IP。常见错误是误用iptables的视角套到tc filter上。如果必须基于源IP分类(比如区分不同客户端上传),正确路径是:iptables -t mangle -A POSTROUTING -s 192.168.1.100 -j CLASSIFY --set-class 1:10,再用tc filter匹配fw标记。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
规则持久化与调试要点
tc配置重启即失,但硬编码进/etc/rc.local已不推荐(systemd下常失效)。更可靠的方式是:
- 写成独立脚本(如
/usr/local/bin/tc-limit.sh),开头加#!/bin/bash,每条tc命令后加|| true防中断 - 用
systemd服务管理:新建/etc/systemd/system/tc-limit.service,ExecStart指向脚本,WantedBy=multi-user.target - 调试时别只信
tc qdisc show,用iperf3 -c 目标IP实测上传速率,再用tc -s class show dev eth0看各class的sent字节数和drops是否增长 - 注意
burst参数:tbf中设太小(如burst 1kb)会导致TCP ACK频繁丢弃,吞吐断崖下跌;htb中burst由内核自动计算,一般不用显式指定
最易被忽略的是qdisc类型选错——默认pfifo_fast完全不控速,root必须显式指定htb或tbf;还有人把parent 1:0写成parent 1:1导致filter挂错位置,规则静默失效。

















