服务器网络丢包如何定位?Ping、MTR与路由追踪实战

用户反馈"网站时快时慢",监控上看延迟曲线像锯齿,偶尔还出现超时。你 ping 了一下服务器,100 个包丢了 5 个,那这 5 个包丢在了哪里?是自己服务器的网卡、是机房交换机、是运营商骨干网、还是跨境链路?网络丢包这类问题最折磨人的地方在于:它通常是间歇性的,而且你只能看到结果,看不到过程。本文给出一套从本机到公网路径的逐层定位方法,核心工具是 ping、mtr 和 traceroute,核心思路是"先分层、再定段、最后定因"。

一、先把丢包量化:别凭感觉判断

排查的第一步不是抓包,而是拿到可信的量化数据。单次 ping 的默认输出信息太少,建议用固定包数、固定间隔的方式采样,得到丢包率、延迟分布和抖动三个指标。

# 发送 100 个包,间隔 0.2 秒,超时 2 秒,最后输出统计
ping -c 100 -i 0.2 -W 2 203.0.113.10

# 只看统计摘要(-q 精简输出)
ping -c 100 -i 0.2 -W 2 -q 203.0.113.10

# 指定源地址 ping(多网卡/多 IP 服务器排查时必须指定,否则可能走错出口)
ping -c 50 -I eth0 203.0.113.10

# 探测路径 MTU:-M do 表示不分片,1472 + 28 字节头部 = 1500
ping -M do -s 1472 -c 5 203.0.113.10

看结果时关注 三个数:丢包率(packet loss)、平均延迟(avg)、最大延迟与标准偏差(mdev 或 stddev)。判断标准可以这样定:丢包率 0% 但 mdev 很大(比如平均 30ms、最大 300ms),说明链路拥塞或存在排队抖动,对实时业务(语音、游戏、交易)影响很大;丢包率 1% 以内且延迟稳定,通常属于背景噪音,不必过度反应;丢包率超过 3% 就需要定位原因了,尤其是当丢包呈现"成串出现"(连续丢十几个包)而不是随机分布时,几乎一定是链路拥塞或设备限速。

二、第一层:本机网卡与内核

先确认包不是在自己机器上丢的。这一层最容易查,也最容易被跳过。

# 查看网卡收发统计,重点关注 errors / dropped / overruns / frame
ip -s link show eth0

# 查看网卡速率、双工模式与链路状态
ethtool eth0

# 查看网卡硬件层详细计数(丢包、错包、miss 等)
ethtool -S eth0 | grep -iE 'drop|error|miss|timeout'

# 各网卡字节/包数统计
cat /proc/net/dev

# 内核协议栈统计:重传、监听队列溢出、丢包
netstat -s | grep -iE 'retransmit|overflow|drop|listen'
nstat -az | grep -iE 'retrans|drop'

# 内核日志里常藏着关键线索
dmesg -T | grep -iE 'eth0|link up|link down|overflow|conntrack'

几个必须认识的关键信号:

  • "nf_conntrack: table full, dropping packet":连接跟踪表满了,高并发服务器上非常常见。用 sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max 查看当前值与上限,前者接近后者即为瓶颈。
  • "TCP: request_sock_TCP: Possible SYN flooding":SYN 队列溢出,通常伴随半连接攻击或突发连接洪峰,需检查 net.ipv4.tcp_max_syn_backlog 与 tcp_syncookies。
  • 网卡 RX dropped / overruns 持续增长:说明内核取包的速度跟不上网卡接收速度,常见于突发大流量或网卡 Ring Buffer 过小,可考虑调大 ethtool -G eth0 rx 4096。
  • errors / frame 非零:物理层问题,可能是网线、光模块、交换机端口故障,需要联系机房。

三、第二层:局域网与网关

确认本机无误后,先 ping 同网段的其他机器,再 ping 网关。这一步的作用是划清"机房内部"与"公网"的界限。

# 查看本机路由表,确认默认网关
ip route show
ip route get 203.0.113.10

# 查看 ARP 表(同网段不通时,先看 ARP 是否正常)
ip neigh show

# ping 网关,确认机房内部链路
ping -c 50 -q 网关IP

判读:如果 ping 同网段机器就丢包,问题在机房内部交换网络;ping 网关正常但 ping 公网丢包,问题在机房出口或公网链路;ping 网关就丢包但同网段正常,可能是网关设备限速或上联拥塞。这条分界线非常重要,它决定了你该联系机房还是该联系运营商。

四、第三层:公网路径 —— 用 MTR 定位丢在哪一跳

mtr 结合了 ping 与 traceroute 的能力,能对路径上每一跳都做持续的丢包统计,是定位公网丢包的核心工具。它输出的每一跳都有独立的丢包率,你只需要看"丢包从第几跳开始出现"。

# 最常用:报告模式 + 宽输出 + 100 个包 + 不解析域名
mtr -rw -c 100 --no-dns 203.0.113.10

# 默认 UDP 模式,某些网络会优先丢弃 UDP,可改用 TCP 模式贴近真实业务
mtr -rw -c 100 --tcp --port 443 --no-dns example.com

# 也可以用 ICMP 模式(最贴近 ping 的结果)
mtr -rw -c 100 --icmp --no-dns 203.0.113.10

# 交互式查看(不带 -r 时实时刷新,排障现场很直观)
mtr --no-dns 203.0.113.10

# 没有 mtr 时用 traceroute / tracepath 做路径探测
traceroute -n -T -p 443 example.com
tracepath -n 203.0.113.10

4.1 怎么读 MTR 的结果

列含义判读要点
Loss%该跳的丢包率这是最重要的一列,但要结合前后跳一起看
Snt已发送包数样本量太小不可信,建议至少 100
Last / Avg / Best / Wrst最近 / 平均 / 最好 / 最差延迟Wrst 与 Avg 差距大说明抖动严重
StDev延迟标准偏差持续大于平均值的 50% 说明链路不稳定

这里有一条必须掌握的判读规则:丢包要从后往前看。如果中间某一跳显示 20% 丢包,但它后面所有跳的丢包率都是 0%,那么这一跳的丢包几乎可以肯定是路由器对 ICMP 的控制平面限速(ICMP rate limiting),并不影响实际业务转发——路由器转发数据包的优先级远高于回应 ICMP。反过来,如果从第 N 跳开始,之后每一跳都持续丢包,那么问题就在第 N 跳到第 N+1 跳之间。

另外要注意协议差异:很多网络会优先丢弃 UDP 或 ICMP 探测包,导致 mtr 显示的丢包率高于业务真实丢包率。因此排查业务问题时,更推荐用 mtr --tcp --port 实际业务端口,结果更接近真实体验。

五、丢包模式识别:从现象反推原因

丢包现象可能原因验证方法处理方向
延迟稳定但持续少量丢包链路轻度拥塞或 QoS 策略mtr 看丢包起始跳联系机房/运营商,或更换线路
丢包集中在每天固定时段业务高峰带宽打满sar -n DEV 1 看 txkB/s 是否接近带宽上限扩容带宽或做流量分流
突发大流量时丢包激增带宽突发上限、连接表满、SYN 队列溢出dmesg 与 nf_conntrack_count调大连接表与 backlog,开启 syncookies
大包不通、小包正常MTU 不匹配或分片被丢弃ping -M do -s 1472 逐步减小 -s 值测试修正 MTU,或开启 MSS 钳制
仅 TCP 大文件传输慢丢包导致拥塞窗口反复收缩ss -ti 看 retrans 与 cwnd定位链路丢包;必要时调拥塞控制算法
跨境/跨运营商丢包明显国际出口或互联互通节点拥塞mtr 看丢包发生在哪一跳、属于哪个 ASN更换专线/BGP 线路或接入加速服务
只有入方向丢包机房入口清洗或黑洞阈值联系机房确认是否有流量清洗接入高防或 CDN 隐藏源站

六、标准排查步骤

  1. 量化基线:用 ping -c 100 -i 0.2 -q 记录丢包率、平均延迟、最大延迟和抖动,同时确认这是持续现象还是偶发。
  2. 确认方向:从服务器 ping 外部、从外部 ping 服务器,双向各测一次。入方向丢和出方向丢,原因完全不同。
  3. 排除本机:查 ip -s link、ethtool -S、netstat -s、dmesg,确认网卡无错包、连接表没满、无 SYN 告警。
  4. 界定机房内部:ping 同网段机器与网关,划清"机房内"和"公网"的分界。
  5. 定位公网段落:用 mtr -rw -c 100(必要时加 --tcp --port 业务端口)找到持续丢包的起始跳,并判断属于哪个运营商或 ASN。
  6. 交叉验证:换一个目标地址、换一段时段、换一条线路(如手机热点)复测,排除单点是偶然因素。
  7. 留证与上报:保存完整的 mtr 报告、ping 统计、时间戳,提交给机房或运营商。没有数据的工单通常会被以"未发现异常"结掉。
  8. 处置与观察:根据定位结果扩容、换线或调整内核参数,处理后持续观察 24 小时以上,确认丢包率回落到基线。

七、把丢包监控常态化

丢包是典型的"事后发现就晚了"的指标。建议部署持续的主动探测,把数据留存下来。最简单的做法是一个循环脚本记录丢包率,生产环境更推荐用专门的拨测或 smokeping 这类工具,把多个探测点到目标机的丢包与延迟画成时间序列。

# 简易丢包记录:每分钟采样一次,追加到日志
while true; do
  echo "$(date '+%F %T') $(ping -c 10 -q 203.0.113.10 2>/dev/null | grep -oE '[0-9]+% packet loss')"
  sleep 60
done | tee -a /var/log/ping-monitor.log

# 观察内核重传情况(retrans/s 持续大于 0 即说明有丢包)
sar -n ETCP,TCP 1 10

# 查看具体连接的重传统计
ss -ti | grep -i retrans

监控指标上,建议至少覆盖:到网关的丢包率、到几个公共 DNS 的丢包率、出方向带宽利用率、TCP 重传率。这四项组合起来,基本能在问题扩大之前就给出信号。

小结

网络丢包定位的核心是把"端到端的结果"拆成"分段的过程"。具体做法是:先用 ping -c 100 拿到可信的丢包率与抖动数据;再用 ip -s link、ethtool -S、netstat -s、dmesg 排除本机网卡与内核;然后 ping 网关划清机房内外;最后用 mtr -rw -c 100 定位公网路径上持续丢包的起始跳。判读 mtr 时牢记"从后往前看":单跳丢包而后续跳正常多为 ICMP 限速,连续多跳丢包才是真实故障。

避坑建议

  • 不要把中间的 ICMP 限速当成丢包:这是新手最常见的误判。判断依据是后续跳是否也丢,以及用 TCP 模式复测一次。
  • 不要只用 UDP 模式的 mtr 下结论:很多网络优先丢 UDP,结果会高估丢包率。排业务问题请用 --tcp --port。
  • 不要忽略连接跟踪表:高并发机器上,"丢包"的真凶往往是 nf_conntrack 表满而不是链路问题,dmesg 里会有明确提示。
  • 不要忘记测双向:只从服务器往外 ping,可能完全看不到入方向的丢包,而入方向丢包往往才是用户感知到的那个。
  • 不要在没数据时提工单:机房和运营商需要处理依据,附上带时间戳的 mtr 报告和 ping 统计,处理效率会高很多。
  • 不要一发现丢包就换机房:先确认是持续性还是偶发性、是带宽打满还是链路质量。很多丢包其实是自己业务高峰把带宽跑满造成的,扩容比迁移更划算。