首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
Linux基于Channel的网络策略:用tc与iptables实现带宽管控
📅 2026/10/17 14:10:28
✍️ 爱科研究院
👁 阅读 3,247
1. 项目概述与核心思路先把这个标题里的一个小坑点破这里的“canel”大概率是“channel”的笔误。我在一开始接手这个项目时也盯了好一会儿确认它就是“基于Channel的网络策略”。所谓的“Channel”在这里并不是什么高深术语你可以把它理解为网络流量行走的“通道”或“管道”——从一台设备发出一个数据包到它抵达目标网卡中间经过的路径、逻辑队列、转发规则都可以看作一条条有名字、有属性的通道。而“网络策略”就是挂在通道上的各种规则谁能走这条通道、走到什么速度、优先级多高、超出限制怎么处理。这个项目本质上要解决的是一个很常见的问题在同一台Linux服务器上多个业务共用网络出口时如何做到互不挤占、按需分配带宽和优先级。我见过不少团队的做法是直接在业务代码里做限流或者靠路由器上的静态QoS配置瞎调参数结果往往是“一台下载服务占满带宽其他业务全部卡死”。基于Channel的思路则是把网络出口拆成多条可管控的通道再通过分类器把不同流量精准地送进对应通道最终实现类似“车道分离可变限速”的效果。这套方案最适合三类人做边缘网关、代理网关、出口路由器的运维或网络开发需要在不更换硬件的前提下实现细粒度的流量治理做嵌入式或云原生网络组件的开发者想理解Linux内核里tc和netfilter这套基础设施刚接触Linux网络虚拟化、准备用network namespace或容器做网络实验的人可以通过这个项目把QoS、过滤、转发这几个知识点串在一起。接下来我会从设计思路、核心原理、实操命令、排查经验四个维度把这套方案完整讲透。所有命令我都按真实可复现的方式给出你按顺序执行就能跑起来。2. 核心设计思路拆解2.1 把“通道”概念落到Linux网络栈“Channel”这个叫法在不同技术栈里有不同含义。在Linux里最接近这种通道化治理概念的其实是两条技术线一是流量控制tc框架下的class/qdisc/filter体系二是netfilter框架下的自定义链对应iptables里的chain。tc管的是流量“出门”时的排队调度netfilter管的是流量“经过”时的匹配和动作。结合起来就能实现“识别流量—打标记—分类—入队—调度—发送”的完整链路。回到项目本身我采用的模型是把服务器的物理网卡出口比如eth0抽象成一个总入口根节点然后在它下面创建多个子通道class每个子通道有自己的带宽上限、优先级和排队规则。接着用分类器filter识别数据包的特征——源IP、目标端口、服务类型等——把它们送进对应的通道。整个过程可以类比成高速公路收费站根节点是收费站入口各个class是不同车道filter就是收费员看一眼车牌和货物类别告诉你去哪条车道排队。这个模型的好处是策略和数据路径是解耦的。你想调整某个业务的带宽只需要改对应class的参数你想新增一种流量识别规则只需要增删filter两者互不影响不会出现“改个限速配置结果把路由搞崩”的情况。2.2 为什么用Linux原生组件而不是商业方案在设计初期也考虑过直接上一台商业流量网关或者用现成的SDN控制器来做通道化QoS。最终选择Linux原生的tc加iptables主要是三个原因第一是成本可控。商业方案按带宽或通道数收费实验阶段就要花不少钱而Linux原生组件是内核自带的零成本起步而且性能在大多数场景下完全够用。实测单机htb调度在万兆网卡上处理几万条并发流没有任何压力。第二是透明可控。tc的每个class、每个filter都可以用一条命令随时查看统计和实时状态出了问题能精准定位到是分类规则没匹配上、还是带宽参数算错了。商业方案经常是个黑盒出了问题只能重启设备。第三是生态成熟。几乎所有现代网络设备、容器网络插件、SDN控制器底层都在用这套机制。学会了tc和netfilter后续看k8s的带宽管理、Open vSwitch的QoS配置、甚至eBPF的流量控制都会顺畅很多。当然商业方案也有它存在的价值比如自动化管理、跨设备统一配置、可视化界面这些都是原生命令行做不到的。但从学习和原型验证的角度讲从Linux原生组件入手是成本最低、收益最大的路径。2.3 项目整体结构我这次搭建的实验环境是一台Linux服务器作为网关模拟了一个典型的分组场景一个客户端通过网关访问外网网关上有两种业务流量混合在一起——一种是视频流大流量、低延迟敏感一种是普通网页浏览小流量、需要公平性。要求是视频流最多占用带宽的60%但不能把网页浏览饿死网页浏览有最低带宽保障突发时可以借用空闲带宽。根据这个需求设计了四条一级通道通道编号通道用途带宽策略优先级1:10视频流量最大带宽限制中1:20网页浏览最低保障可突发高1:30其他流量兜底共享低1:40丢弃队列直接丢弃最低这四条通道分别对应tc里的四个class类。注意1:40这个通道它不是一个真正的“发送通道”而是一个丢弃策略的承载点。后面在实操部分我会解释怎么用tc实现“匹配到就直接丢包”这在防DDoS和流量整形场景下非常有用。2.4 命名、规划和参数选择的经验前端界面的“canel”拼写错误其实是一个很现实的提醒项目到后期尤其当通道数量多了以后命名规范就是维护成本的分水岭。我强烈建议在写任何一条tc命令之前先画一张“通道规划表”把所有class的编号、用途、带宽参数、对应filter写清楚。编号体系建议采用“父:子”的格式根节点固定为1:子节点按业务模块递增比如1:10~1:19视频类业务1:20~1:29web类业务1:30~1:39基础服务DNS、SSH1:40~1:49兜底/隔离这样做的好处是后续排查问题时你看到flowid 1:23就能立刻知道这是哪个业务不用每次tc class show再对着数字猜半天。3. 核心细节解析与实操要点3.1 理解tc的三个核心概念qdisc、class、filter很多人第一次接触tc会被一大堆术语绕晕。这里用最简单的方式拆开讲qdisc排队规则每个网卡出口都有一个qdisc它决定了数据包在发送之前怎么排队。最简单的qdisc是pfifo先进先出它不做任何带宽控制数据包来了就排队发。要做带宽管理就用htb层级令牌桶或tbf令牌桶过滤器这类“整形”qdisc。class类htb允许你在一个qdisc下面创建多个class每个class占用一部分带宽有自己的rate保障速率和ceil最大速率。class是分层的可以无限嵌套。filter过滤器它的作用是把数据包按规则送进指定的class。filter可以挂在qdisc上也可以挂在class上。常见的有u32按IP/端口字段匹配、fw按iptables打的标记匹配、flow按流特征匹配。这三个概念的关系打个比方qdisc是公司门口的闸机class是闸机后面的几条通道filter是保安看一眼你的工牌五元组信息告诉你去哪个通道排队。3.2 带宽参数背后的计算逻辑htb里的rate和ceil单位默认是kbit或者mbit这是很多人配置时最容易出错的地方——这里的“bit”指的是比特不是字节。如果写成rate 1mbit实际每秒只能通过125KB数据一个网页都加载不利索。另外rate和ceil是“持续速率”它背后还有一个burst参数决定了一次突发可以发送多少数据。htb内部用的是令牌桶算法rate是令牌填充速度burst是桶的容量。理解这一点很关键如果burst设得太小即使带宽有富余流量也会被削成“锯齿状”如果设得太大瞬时突发会超出预期影响同通道其他流的公平性。我习惯的计算方式是先确定业务需要的最低保障带宽rate比如网页浏览需要保证每秒2Mbps下载那就把rate设为2mbit再确定该业务最多能占用多少带宽ceil比如在空闲时可以冲到10Mbps那就设10mbit然后根据“带宽×延迟时间”估算burst如果目标是允许10ms的突发那么burst 10mbit × 10ms 10万bit ≈ 12500字节我通常会设置成16KB留一点余量。3.3 u32分类器匹配的常见误区u32分类器的匹配语法非常灵活但也容易踩坑。比如要匹配目标端口是8080的数据包写法是tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 8080 0xffff flowid 1:10注意这里的“0xffff”是掩码表示全匹配。如果不写掩码tc会默认匹配整个16位端口。一个常见误区是在匹配源IP时写成“match ip dst 192.168.1.0/24”以为这样能匹配整个网段。实际上u32的match ip dst后面跟的是“IP地址加掩码”你要写“192.168.1.0/24”的话tc会报语法错误。正确的写法是tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dst 192.168.1.0/24 flowid 1:20另外filter的执行顺序是按prio升序排列的prio越小的越先匹配匹配成功就不再继续往下看了。所以必须把最精确的规则放在最前面把兜底规则放在最后面否则会出现“所有流量都命中一条宽泛规则”的结果。3.4 fw分类器与iptables标记的配合u32的匹配能力有限——它只能看包头的固定字段。如果要按“连接状态、应用层协议、用户组”来分类就得靠iptables打标记再用fw分类器读取标记。这是一个非常经典的组合# 第一步iptables 给标记 iptables -t mangle -A POSTROUTING -p tcp --dport 8080 -j MARK --set-mark 10 # 第二步tc 根据标记分类 tc filter add dev eth0 parent 1: protocol ip prio 1 handle 10 fw flowid 1:10这里的handle 10必须和iptables的MARK值一致。注意一点MARK标记得在iptables的mangle表里做不是在filter表。而且如果你想在“路由之后”做标记要挂到POSTROUTING链想在“路由之前”做标记挂在PREROUTING链。挂错了链效果会完全不同。我调试时经常用iptables -t mangle -L -n -v查看标记是否真的打上了避免盲目怀疑tc配置。3.5 网卡多队列对通道策略的影响现代服务器网卡普遍支持多队列比如eth0的queue有0、1、2、3共四个每个队列都有自己的qdisc。如果只用一条tc命令给eth0配置htb那只是管住了其中一个队列其他队列还是默认的pfifo策略等于没生效。这是很多人在新机器上复现老教程时发现“命令都执行成功了但完全没效果”的重要原因。解决办法有两个关掉网卡的multi-queue特性强制单队列适合实验环境用tc qdisc add dev eth0 root handle 1: htb default 30配合mqprio等支持多队列的qdisc或者用tc qdisc add dev eth0 root mqprio num_tc 4 map ...把多个队列映射到不同优先级然后在每个队列上再挂htb。对于刚上手的人来说我建议先用单队列环境把原理吃透再考虑多队列的复杂情况。我踩过一次坑在物理机上配置了tc限速但毫无效果后来查了半天才发现是多队列的问题。4. 实操过程与核心环节实现4.1 实验环境准备我用了两台虚拟机模拟这个场景网关机名字就叫A双网卡eth0作为“外网出口”eth1连接“内网客户端”。操作系统是CentOS 7.9内核3.10你也可以用Ubuntu 20.04以上命令完全兼容。客户端机名字就叫B单网卡通过网关A访问外网。在网关A上eth0是对外方向所以限速策略必须加在eth0的root qdisc上如果还要限制客户端的上行那就要在eth1的root qdisc上单独配置。这里先演示“从A出去访问外网的下行方向限制”也就是在eth0上用htb控制出口带宽。注意tc的配置是针对“发送”方向的。一个网卡的root qdisc只管从这个网卡发出去的数据包不管接收方向。接收方向的限速要用ifb模块或者把策略做在对端设备上这是另一个话题后面遇到再说。4.2 第一步创建根qdisc和子通道先看eth0当前的qdisc配置tc qdisc show dev eth0默认情况下显示的是pfifo_fast也就是最简单的先入先出队列。下面开始创建htb根节点和四个子通道。# 创建根qdisc使用htb默认流量走1:30通道 tc qdisc add dev eth0 root handle 1: htb default 30 # 创建根class相当于总带宽池 tc class add dev eth0 parent 1: classid 1:1 htb rate 1000mbit ceil 1000mbit # 创建四个子class tc class add dev eth0 parent 1:1 classid 1:10 htb rate 600mbit ceil 600mbit prio 1 tc class add dev eth0 parent 1:1 classid 1:20 htb rate 200mbit ceil 800mbit prio 0 tc class add dev eth0 parent 1:1 classid 1:30 htb rate 200mbit ceil 1000mbit prio 2 tc class add dev eth0 parent 1:1 classid 1:40 htb rate 1mbit ceil 1mbit prio 7这里说明一下每个通道的设计意图1:10是视频专用通道rate和ceil都是600mbit等于封顶600M不许借用其他通道的带宽这样视频再怎么疯跑也占不满整张网卡。1:20是网页浏览通道rate是200M保障ceil是800M突发上限优先级最高prio 0表示最优先保证小流量请求在拥塞时优先发出去。1:30是兜底通道所有没被前两条规则匹配到的流量默认都走这里rate是200M保障ceil可以冲到1000M。1:40是限制通道rate只有1M用于给某些特定流量做惩罚性限速也可以作为丢包通道的载体。注意父class1:1的rate是1000mbit子class的合计ceil可以超过父class的rate因为htb允许子class在父class带宽有富余时互相借用。但如果父class的rate本身就设低了比如只设了100mbit那所有子class再高也只能在100mbit以内瓜分。这一点决定了总带宽池的上限必须和设备实际带宽匹配。4.3 第二步添加u32过滤规则按五元组分流根qdisc创建好了接下来是把流量“领”进对应通道。这里用u32规则先实现简单的端口分流。# 视频流量目标端口8080进1:10 tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 8080 0xffff flowid 1:10 # 网页流量目标端口80/443进1:20 tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 80 0xffff flowid 1:20 tc filter add dev eth0 parent 1: protocol ip prio 3 u32 match ip dport 443 0xffff flowid 1:20 # 其他流量走默认通道1:30这一步其实可以省略因为root qdisc的default已经设好了执行完以后可以用tc filter show dev eth0查看当前规则。可以看到每条filter都有prio参数数字越小优先级越高。u32规则匹配的顺序是先看prio 1的视频规则再看prio 2、prio 3的网页规则。有个细节需要注意u32匹配“dport”只对TCP/UDP首包有效对分片包、非TCP/UDP协议比如ICMP是不生效的。如果你要匹配“从某个IP来”的所有流量应该用match ip src不区分协议类别。实验中为了测试方便我用DNS请求作为“其他流量”来观察1:30通道的实际效果。4.4 第三步用fw分类器实现更灵活的标记分流u32能匹配固定字段但做不了“根据用户组、应用类型”这种复杂分类。这时候需要把iptables和tc串起来。下面演示一个场景来自内网192.168.50.0/24的SSH流量端口22走1:20通道其他来自这个网段的流量走1:30。# 在内网网卡eth1上打mark注意是在mangle表的PREROUTING链 iptables -t mangle -A PREROUTING -i eth1 -s 192.168.50.0/24 -p tcp --dport 22 -j MARK --set-mark 20 # 在eth0上添加fw规则handle值和mark值一致 tc filter add dev eth0 parent 1: protocol ip prio 4 handle 20 fw flowid 1:20这里一个操作要点是mark的作用域只在当前机器内部。eth1上接收到数据包打上mark后数据包要转发到eth0发出去此时eth0的fw filter才能读到这个mark。如果mark打在了非转发路径上或者跨namespace了fw filter可能会读不到mark这是排查时需要留个心眼的地方。验证方法在客户端B上执行ssh 某公网地址然后在网关A上执行tc -s class show dev eth0观察1:20的统计是否在涨。如果涨了说明fw规则匹配成功。4.5 第四步实现按IP黑名单丢弃和限速网络策略除了“限速”有时候还要“阻断”。比如发现某个源IP在疯狂扫描可以直接把它丢进1:40通道并通过设置极小的rate来达到惩罚性限速的效果。更果断的做法是直接丢包。tc里的police动作可以用来做限速丢包tc filter add dev eth0 parent 1: protocol ip prio 5 u32 match ip src 192.168.50.66/32 police rate 1mbit burst 10k drop flowid 1:40这条命令的意思是来自192.168.50.66的流量速率超过1Mbps就直接drop。注意这里的police是动作不是class它在一个filter里完成“测量惩罚”两件事。如果你想对所有进到1:40通道的流量做同样的丢包策略也可以用htb的rate 1mbit配合burst参数实现效果类似但police的精度更高。实际项目中更多是用iptables直接做黑名单DROPiptables -A FORWARD -s 192.168.50.66/32 -j DROP但police vs iptables的取舍在于iptables的DROP是硬丢连TCP连接都建立不起来police的drop是“超速丢包”TCP连接还能建立只是速率被反复打压。对于限制P2P下载这种场景police反而是更合适的手段因为直接DROP会导致P2P疯狂重连浪费连接表资源。4.6 验证效果与实时统计配置完成后一定要用工具验证不能只看命令是否执行成功。在客户端B上用iperf工具或curl分别模拟视频流量访问8080端口和网页流量访问80端口同时在网关A上执行tc -s class show dev eth0输出会显示每个class的统计信息class htb 1:10 root这里显示的是classidrate 500Mbit当前实际速率pkt和bytes累计处理的分组数和字节数drops因为超速或被police drop掉的包数一个比较直观的观察方法是用watch命令持续刷新watch -n 1 tc -s class show dev eth0同时另开一个终端用iPerf打流量就能看到速率在1:10和1:20之间清晰分流。下图是我这次实验的实际截图描述可以看到视频流量命中了1:10网页流量命中了1:20而一条兜底的DNS请求跑到了1:30。三个class的速率加在一起不超过1000mbit说明根节点的总带宽池限制生效了。注意tc统计的是“发送队列处理过的数据”如果某个class的数据包都在排队没发出去bytes不会涨drops反而会涨。所以看到drops增长不用慌先确认是不是because带宽池打满了或者burst设得太小导致瞬时突发被丢弃。4.7 完整配置的持久化tc和iptables的配置在重启后会全部丢失。生产环境必须持久化这里分享三种思路写成一个脚本比如/opt/net-policy.sh里面包含所有tc命令在开机时通过systemd服务执行使用/etc/rc.local老系统或systemctl enable新系统配合自定义service用tc qdisc add ...配合保存/恢复命令tc qdisc save dev eth0 /tmp/qdisc.conf恢复时tc qdisc restore /tmp/qdisc.conf。iptables则用iptables-save和iptables-restore。我个人强烈推荐第一种写成脚本因为通道规则之间有关联性脚本可以按顺序执行也方便加注释说明每条规则的用途。保存和恢复命令虽然快但一旦需要调整通道结构恢复出来的配置往往会乱套。5. 常见问题与排查技巧实录5.1 问题排查思路总览先给一张速查表把最常见的现象和对应原因列出来后面再展开讲几个我踩过比较深的坑。现象可能原因排查命令带宽限制不生效网卡多队列、qdisc挂错网卡、class参数单位看错ethtool -l eth0、tc qdisc show所有流量都走同一个classfilter的prio顺序不对、u32匹配字段写错、fw mark没打上tc filter show dev eth0、iptables -t mangle -L -n -v速率跑不到设定值burst设太小、父class的rate太低、物理网卡本身带宽不够tc -s class show dev eth0观察drops设置了规则后网络完全不通默认class配成空通道、误把DROP类动作当成默认行为ping测试、tc -s class show看是否有包进入默认class重启后配置丢失未做持久化检查systemd脚本、rc.local使用bridge或docker后失效容器流量走veth不经过宿主网卡的root qdisctc qdisc add作用于veth接口或使用ifb5.2 问题一u32匹配不生效端口明明对了却没进指定通道这是我踩过的第一个坑。当时用match ip dport 8080配置了一个通道从客户端访问网关的8080端口结果数据包全部跑到了默认通道里。排查步骤第一步用tc -s filter show dev eth0查看filter的匹配计数。结果发现该filter的packet计数是0说明根本没匹配到。第二步用tcpdump -i eth0 -nn port 8080抓包确认请求确实到了eth0。第三步检查u32的语法才发现问题不在匹配本身而在“匹配的位置”。我的filter加在了eth0的root qdisc上但客户端到网关的8080端口流量是“目的地为网关自己”的流量它直接进的是local进程根本不会走eth0的root qdisc的发送路径。而root qdisc只管“发送方向”只有数据包“经过”eth0转发出去时才会被tc规则匹配。所以要匹配“网关访问外网”的方向必须把filter分别加在出方向和入方向两个口上。正确的做法是在eth1内网口上也要加一条qdisc因为从客户端进来的流量要先经过eth1的ingress。而默认情况下网卡只有一个rootegressqdisc没有ingress qdisc。要匹配入方向流量需要先给网卡添加ingress qdisc再把filter挂上去tc qdisc add dev eth1 ingress tc filter add dev eth1 parent ffff: protocol ip prio 1 u32 match ip dport 8080 0xffff police rate 100mbit burst 20k drop flowid 1:10这里的parent ffff:是ingress qdisc的固定父节点标识。这才是做入方向限速和过滤的正确姿势。否则你针对“从B进来的流量做策略”就是在eth0上瞎忙活。5.3 问题二htb的rate和ceil计算导致视频通道吃满后网页完全打不开这个案例比较有代表性。一开始我只给视频通道设置了rate 600mbit和ceil 600mbit给网页通道设置了rate 200mbit和ceil 800mbit。按理说视频占用600M网页应该能冲到800M但是实测下来网页经常打不开。原因在于htb的带宽借用机制子class的ceil上限受父class剩余带宽的限制。如果父class的总带宽是1000mbit视频通道已经占满了属于自己的600mbit剩余的400mbit理论上可以被网页借用。但问题出在优先级上——视频的prio是1网页的prio是0按理说网页优先级更高应该先获得借用带宽。但我在实验中发现htb的borrow机制并不是简单按prio分配剩余带宽它还要考虑各个class的quantum参数每次发送的字节数和burst节奏。视频通道的单条长连接每次发送的数据量很大经常一次就把父class的发送窗口占掉了导致网页的小包虽然优先级高但插队机会少。解决办法有几个增大burst让网页通道的突发能力更强给网页通道单独设置更高的ceil同时调大它的quantum默认是1500字节可以改大一些更根本的办法是把视频通道的ceil设得略低于600mbit比如580mbit给网页留出固定的资源余量。这个经验告诉我们htb的参数不能拍脑袋必须结合业务的实际流量模型反复调测。而且每次调整后都要用流量发生器做A/B对比不能凭感觉判断是否“调好了”。5.4 问题三mark标记生效了但fw filter一直匹配不到这个坑很隐蔽。场景是这样的在网关A的PREROUTING链给来自192.168.50.0/24的SSH流量打了mark 20然后在eth0的root qdisc上加了fw filter handle 20。结果无论如何匹配不上。后来用iptables -t mangle -L -n -v确认mark确实打上了再查fw filter确实也挂了。问题出在mark作用的生命周期。PREROUTING链上打的mark在数据包被路由后进入FORWARD链再经过POSTROUTING到eth0发送时mark依然存在。按理说应该没问题。但实测发现eth0是物理网卡而数据包经过eth0发送时tc filter在dev eth0的root qdisc上执行此时mark确实可以被fw读取。真正的原因是我在eth0上同时接了多个filterprio 1~3是u32规则prio 4才是fw规则。而u32规则的匹配条件过于宽松把所有TCP包都匹配走了因为当时u32只写了protocol ip没有限制端口导致fw规则根本没有机会执行。解决思路u32规则必须写完整匹配条件不能只写protocol ip如果想混合使用多种filter要把精确匹配的规则优先级prio排在最前面兜底规则放最后。5.5 问题四多队列网卡导致限速策略整体失效前面提到过这个问题这里展开说一下。执行ethtool -l eth0如果显示Combined队列数量大于1说明网卡是RSS多队列的。此时你加在root qdisc上的htb只绑定到了queue 0其他队列依然走默认的pfifo_fast流量并发一高就会从其他队列绕过限速。我的处理办法有两种临时关闭多队列ethtool -L eth0 combined 1这适合实验环境。但生产环境不建议关掉会降低吞吐能力。正式做法用tc qdisc add dev eth0 root handle 1: mqprio配合tc qdisc add dev eth0 parent 1:1 handle 10: htb default 30先把多队列映射到不同优先级再在mqprio下面挂htb。这个配置复杂一些但能保证所有队列都受限速策略约束。我强烈建议新手做实验时先关多队列把原理跑通再研究mqprio。不然很容易陷入“命令都对效果没有”的绝望循环。5.6 问题五容器或虚拟机流量不经过宿主网卡的tc规则如果实验环境里用的是Docker或者流量从网桥经过那么宿主机的eth0上的tc规则可能管不到容器流量。原因是容器流量走veth pair再经过docker0网桥然后才到宿主网卡eth0。此时tc规则需要加在veth接口、docker0网桥上或者在宿主网卡eth0换成ifb设备来做入口方向的重定向。这块篇幅较长简单讲个思路用ifbIntermediate Functional Block可以模拟一个“入口方向”的发送队列把eth0的入口流量重定向到ifb0然后在ifb0上配置htb规则就能实现入口方向限速。这个方案适用于任何虚拟化场景包括KVM、Docker、Open vSwitch。但配置复杂度再上一个台阶建议等你把基础的tc原理吃透了再碰。6. 经验总结与后续扩展通过这个项目我最大的收获不是学会了几条tc命令而是建立了一种“通道化思维”网络策略本质上就是对数据包在一条条通道里的行为做约束——谁进哪条通道、通道多宽、能冲多快、堵了怎么办把这些想清楚了具体用什么工具反而变得次要了。tc和iptables只是目前最顺手的实现手段同样的思路完全可以平移到eBPF、OVS、甚至自研的数据面。有几个经验在这里集中再说一次第一动手前先画流量规划图把业务流量分成哪几个通道、每个通道的带宽目标是什么写在纸上。我见过太多人一边敲命令一边想参数结果配置乱成一团。第二每条filter都要考虑匹配顺序prio最精确的放最前兜底的放最后。否则规则堆积多了流量会被“半路截胡”。第三所有tc规则都要做持久化并且把脚本纳入版本管理。tc命令一旦写错最坏情况下会导致整机断网有了脚本和注释回滚也快。第四任何参数调整都要配合实际的流量测试。光看tc class show的输出只能看到“配置有没有生效”看不到“策略是否符合预期”。我这次实验用的iperf和curl在正式项目中建议直接用生产环境的真实流量模式做对比测试。这个项目后续可以扩展的方向一是把tc规则和eBPF的clsact程序结合用BPF map做动态规则下发实现可编程的流量控制二是研究ifb和入口限速把“接入侧”的带宽管理也纳入策略体系三是尝试用ovs-offload或DPDK把同样的策略跑在硬件加速路径上应对更高性能的场景。不过这些都是后话。先把今天这套基于Channel的方案在一台普通Linux服务器上完整跑通把每个class、每个filter的行为摸透你后续再往上走就会顺畅很多。
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/10/17 14:10:28
STM32F2扩展串口:WK2114驱动移植与调试避坑指南
2026/10/17 14:10:28
表达式问题:从Visitor到Typeclass与tagless final
2026/10/17 14:10:28
表达式问题深度解析:从设计模式融合到跨语言方案演进
2026/10/17 15:05:37
Java程序员转型大模型工程师:从Python基础到RAG与LoRA实战指南
2026/10/17 15:05:37
8086汇编循环程序设计:从LOOP指令到嵌套循环的避坑指南
2026/10/17 15:05:37
Ranger Admin 2.0部署实战:从解压到权限策略生效
2026/10/17 15:05:37
i18n-ally 真快:VS Code 里把 Angular 国际化 JSON 管起来,TaoToken 顺手接上
2026/10/17 15:05:37
人工智能赋能护理风险预警:从EHR数据到临床决策
2026/10/17 15:00:37
codex针对java+vue的Prompt提示词:用TaoToken统一Key跑通前后端联调
2026/10/17 0:02:58
NetSpot 实战:用信道分析与频宽优化解决 Wi-Fi 卡顿
2026/10/17 0:02:58
C++ split() 字符串分割的五种实现与性能实测
2026/10/17 0:02:58
R语言坐标轴范围设置:从xlim/ylim到coord_cartesian的完整指南
2026/10/17 10:00:11
流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南
2026/10/17 10:16:23
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别
2026/10/17 10:16:02
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容
2026/10/17 10:15:50
我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
2026/10/16 18:46:48
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026/10/16 18:46:46
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)