首页 游戏 软件 排行 专题

三步用tc netem造出200ms延迟,第2步参数写反了

来源: 本站整理 日期:2026/11/3 22:53:57

上周有个客户找我,说他们的订单接口"偶尔超时",但复现极其困难线上跑一天能碰到两三次,日志里只有一句 Read timed out,没有堆栈,没有 5xx,流量监控看着一切正常。客户自己的说法是"可能是网络抖动",但抖多少、抖多久,谁也说不清。

最后我们决定换了个思路:不猜了,直接在服务器上人为制造弱网环境。既然能控制延迟和丢包,就能把"偶尔"变成"每次",问题自然会浮出来。Linux 自带的 tc 命令干这件事是它的老本行,其中 netem 这个队列规则(qdisc)专门用来模拟网络延迟、丢包、抖动、限速这些不理想特性。这一篇就把我这次排查的完整过程和踩到的几个坑写下来。

如果你手上只有一台小机器也想复现这类问题,可以先看看这几家的报价和技术说明:goodlyclouds(美国双 ISP / 英国原生 IP 精品线路)双 ISP 回程线路本身抖动就比普通机房小很多,做弱网对比实验时更干净;干杯cloud(美西 AT&T 原生住宅宽带独立 IP)的 KVM 实例分钟级开通,拿来临时当实验节点很省事。

Linux 服务器终端运行 tc netem 命令模拟网络延迟

第一步:给网卡挂上 netem,别急着加参数

netem 是挂在网卡出方向(root)的一个队列规则。最小可用的一条命令:

tc qdisc add dev eth0 root netem delay 200ms

执行完不报错,就说明规则挂上了。这时候 ping 一下网关,会发现 RTT 确实多了 200ms 左右。确认生效后再往下走,别一次性把参数全堆上去。

这一步的坑在于netem 会整个替换掉网卡原有的 root qdisc。很多人在上面本来挂过 HTB 做限速、或者挂着 fq 做多队列调度,直接 add 一个 netem 上去,原来那些整形规则全没了。表现出来的现象很迷惑:明明之前限速限得好好的,加完 netem 之后带宽限制失效了。

稳妥的做法是先看一眼现状:

tc qdisc show dev eth0

如果原来已经有别的 root 规则,要么用 tc qdisc change 改,要么把 netem 挂到下层(比如挂在 HTB 的某个 class 下面)。

服务器网卡与网线特写,网络数据流

第二步:参数写反的那一次

我要模拟的是"延迟 200ms,同时丢包 5%"。第一条命令我是这么写的:

tc qdisc add dev eth0 root netem delay 200ms loss 5%

看起来没毛病,但 tc qdisc show 里只有一条 netem,丢包没生效。原因是我把 loss 写在了 delay 后面,参数解析时 loss 被当成了 delay 的修饰参数给吞掉了netem 的参数是按顺序逐个消费的,不是按名字取的。

正确写法是先 limit 再 delay 再 loss,或者干脆每类参数单独一条命令叠加:

tc qdisc add dev eth0 root netem limit 10000 delay 200ms 50ms loss 5%

这里的 limit 也不能省。netem 默认的队列上限是 1000 个包,一旦超了,新到的包直接被丢弃,表现就是"加了 200ms 延迟之后带宽莫名其妙掉了一大截"。这是很多人的第一个疑问:明明我只加了延迟,怎么吞吐也降了?答案就是 limit 太小,队列爆了。

还有一个小坑,delay 后面那个 50ms 是抖动量,意思是延迟在 150ms~250ms 之间随机浮动。如果你想要的是稳定的 200ms,就别加第二个数字,不然你会看到 RTT 一直跳。

网络流量在队列中排队等待的可视化示意图

第三步:删规则时手抖,把自己关在门外

实验做完要恢复。第一种写法:

tc qdisc del dev eth0 root

如果网卡上原本没有 root 规则、或者你删错了设备,这条会报 RTNETLINK answers: No such file or directory,属正常,报完就说明本来就没东西可删。但如果网卡上原本挂着别的业务 qdisc,这一下就把生产规则一起干掉了。

更稳的做法是平时就把实验规则挂在一个单独的 class 下面,删除时只动自己那一层;或者干脆用另一个网络命名空间(ip netns)做实验,规则和真实网卡完全隔离,测完直接删命名空间,不留任何痕迹。

恢复之后一定要验证,别默认删干净了:

tc qdisc show dev eth0
ping -c 5 <目标地址>

我们那次恢复完发现 tc qdisc show 里还残留一条 netem,延迟还有 100ms,整个测试环境的基线全错了,后面的结论差点被带偏。所以"删完必须复测"这条我写进了自己的检查清单。

额外提醒:netem 只管出方向

netem 是挂在网卡 root 上的队列规则,作用的是这台机器发出去的包。回包方向要加在对面那台机器上,或者用 ifb(Intermediate Functional Block)把入方向重定向出来再整形,这是另一个坑了。我们第一版测试就因为只配了出方向,结果"客户端超时、服务端正常",误判成服务端代码问题,浪费了大半天。

弱网实验的最终结论是:客户那条超时链路在延迟超过 120ms 加上 3% 丢包时必现,而代码里有个 HTTP 客户端默认超时写的是 100ms。这事最后是改了两行配置加一次连接池调整解决的,跟服务器性能一点关系都没有如果当初没把弱网环境复现出来,这个锅大概率会扣到服务器头上。

工程师在笔记本上调试命令行并观察延迟曲线

所以 tc netem 这个工具,值得每个做线上排查的人抽半小时熟悉一下。它不能帮你解决任何性能问题,但能帮你把"感觉是网络问题"变成一个可以复现、可以量化、可以写进报告的具体条件。

数据中心机房内高速网络链路抽象渲染

玩家留言 跟帖评论
查看更多评论
相关文章
猜你喜欢
同类下载