当用户反馈页面打不开,接口超时率从 0.1% 飙到了 15%。你 SSH 上去,敲了个 ping baidu.com。
心跳瞬间凉了半截——平时 2ms 的延迟,现在 800ms,偶尔还 Request Timeout。
这种场景,干过运维的都懂。问题来了:下一步该干什么?
大部分人第一反应是重启。重启网卡,重启服务器,实在不行重启业务。但网络延迟高这件事,原因可能出在四个完全不同的地方:你的客户端、中间链路、服务器网卡/内核、或者对端服务扛不住了。找准病灶,才能对症下药。
排查网络延迟,别一上来就抓包。从 ping、mtr 到内核参数调优,手把手教你用 Linux 工具链定位延迟根因。
这篇文章给出一套可复制的排查路径,跟着步骤走就可以了。
我见过最离谱的操作是——延迟一高,上来就 tcpdump -i eth0,抓它几百 MB,然后对着 Wireshark 发呆半小时。
tcpdump 是好东西,但你还不知道问题出在哪一段之前,抓包等于盲人摸象。
第一步应该干什么?分层定位。
ping-c 100 -i 0.1baidu.com-c 100 发 100 个包,-i 0.1 每 100ms 发一个。看三个值:
ping 能告诉你"确实慢了",但说不清"哪里慢了"。这时候得上 mtr。
mtr 是 ping 和 traceroute 的合体,能逐跳告诉你每一跳的延迟和丢包率。
mtr--report--report-cycles 10 baidu.com输出长这样:
HostLoss% SntLastAvgBestWrstStDev1. 192.168.1.1 0.0% 10 0.3 0.4 0.2 0.6 0.12. 100.64.0.1 0.0% 10 1.2 1.5 1.1 3.2 0.63. 202.96.128.68 30.0% 10 15.2 18.4 14.1 29.7 4.84. 218.30.53.165 40.0% 10 18.5 21.2 17.3 35.1 5.35. 220.181.38.174 0.0% 10 16.8 17.5 16.2 19.3 0.9看第 3 跳和第 4 跳:丢包率 30%-40%,但第 5 跳恢复到了 0%。
这就是新手非常容易踩的坑——中间节点丢包,不代表真的丢了数据包。
很多路由器对 ICMP 做了速率限制,它对 ping 不理睬,但你的 TCP 业务流量能够正常通过。
判断方法很简单:如果后续跳的丢包率反而降下来了,那前面的丢包就是假的。 永远以最后一跳(目标 IP)的丢包率为准。
但如果最后一跳也跟着丢包,那就是真有问题了,继续往下看。
如果 mtr 确认最后一跳丢包,问题大概率出在两处:带宽被打满或跨国/跨运营商骨干网抖动。
iftop -n -Pnloadiftop 按连接显示带宽,nload 看整体流量。出口带宽跑到 90% 以上的话,延迟必飙升。原因很简单——数据包在网卡队列里排队等着发,队伍越长,排得越久。
带宽没满但延迟高?看看连接数。
ss -stime-wait 超过几万、或者 listen 队列溢出——也会导致新连接响应慢。
netstat -s | grep -E "listen|overflow|drop"ListenOverflows 在涨?检查 net.core.somaxconn 和应用的 backlog,大概率是这里太小了。
很多人不知道,延迟高未必是网络的问题,也可能是你服务器内核的 TCP 协议栈在影响。
TCP 重传是延迟的头号杀手。一个包发出去没收到 ACK,就得等超时重传——Linux 上的超时至少 200ms,有时候甚至 1 秒以上。
netstat -s | grep retrans输出:
121387 segments retransmitted拿这个数除以总发送段数,就是重传率。超过 1%,就要动手了。
重传原因很多,但最常见也最好修的一个:TCP 接收缓冲区太小。
sysctl net.ipv4.tcp_rmemnet.ipv4.tcp_rmem = 40961310726291456三个值:最小、默认、最大(字节)。默认 128KB,在高速网络下根本不够用。打个比方:带宽延迟乘积(BDP)是 10Mbps × 0.2s = 2Mb = 250KB——默认缓冲区连一个 BDP 的数据都塞不下。装不下怎么办?发送端等着。
怎么修:
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"传统的 Cubic 算法靠"丢包"来感知拥塞——先塞满缓冲区,等丢包了才知道堵车,然后才减速。高延迟链路下,这操作简直是灾难。
BBR 呢?它直接测量瓶颈带宽和最小 RTT,提前建一个路况模型,在丢包发生之前就主动减速。
sysctlnet.ipv4.tcp_congestion_control如果是 cubic,换一下:
sysctl -w net.ipv4.tcp_congestion_control=bbr有人实测过,同一台机器、同一条跨国链路,从 Cubic 切到 BBR 后吞吐提升 2-3 倍,RTT 抖动减少 60% 以上。
下次延迟告警响起,打开这个清单,挨个过:
网络排查这事,80% 的问题出在那 20% 的常见原因上。这九个步骤走一遍,大部分场景都能在五分钟内定位到根因。
不需要你是网络专家,手里有一套好用的工具就行。
Linux性能调优系列
- CPU篇
- 内存篇
- 磁盘篇
- 网络篇
Linux性能优化:网络排查命令ss、ip、tc、ethtool 实战拆解
Linux性能优化:tcpdump + Wireshark 实战指南,网络流量尽在掌握
如果您有更好的理解和建议,可以免费加入知识星球,留言探讨~
