你和目标服务器之间发生了什么
每次访问某个网站很慢的时候,你 ping 了一下,发现延迟不高,但页面就是加载不出来。这种时候问题往往不在终点,而在中途的某一条链路上。你和目标服务器之间,数据包要经过很多台路由器(网络中的转发设备)。任何一台出现问题,都会影响整体体验。
traceroute(路由追踪工具)就是用来查这个的。它能把你到目标服务器的完整路径展示出来,每一跳都显示一个IP地址和对应的延迟时间。而 mtr(My Traceroute,结合了 traceroute 和 ping 的实时网络诊断工具)更进一步,能持续检测每一跳的丢包率和延迟变化,让你直观地看到"慢在哪一跳"。
我第一次用 traceroute 排查公司OA系统访问慢的问题时,发现数据包从公司网关出去后,在某个电信的骨干节点上丢包率高达30%。之前领导一直怀疑是OA服务器有问题,差点要换服务商。排查结果一出来,直接拿着数据找运营商交涉,问题很快就解决了。这就是 traceroute 和 mtr 的价值。
traceroute的工作原理
traceroute 利用了 IP 协议中 TTL(生存时间,Time To Live)字段的特性。TTL 是一个数字,每经过一台路由器就减1,减到0时路由器会丢弃这个包并向发送方回复一个 ICMP(互联网控制报文协议)超时消息。
traceroute 的工作原理是这样的:
1. 先发送一个 TTL=1 的包,第一台路由器收到后 TTL 减为0,回包告知"超时",traceroute 就知道了第一跳的地址。
2. 然后发送 TTL=2 的包,第二台路由器会回复超时。
3. 以此类推,直到到达目标主机。
每跳默认发3个探测包,所以你会看到每行有3个延迟数据。如果某跳显示 * * *,说明探测包没有返回,可能是路由器配置了不回复ICMP的策略,或者网络确实不通。
traceroute的常用参数
基本使用
# 追踪到目标主机的路由路径
traceroute www.example.com
输出看起来像这样:
traceroute to www.example.com (93.184.216.34), 30 hops max, 60 byte packets
1 192.168.1.1 1.234 ms 1.189 ms 1.201 ms
2 10.0.0.1 5.432 ms 5.401 ms 5.389 ms
3 202.96.128.8 12.345 ms 12.301 ms *
4 * * *
5 93.184.216.34 85.123 ms 85.001 ms 84.987 ms
第4跳全是 * 而且第5跳又能到达目标,说明第4跳的路由器不回复ICMP,但数据包实际上通过了。这种情况不需要太担心。如果目标地址一直到达不了,那才是真的故障。
使用ICMP模式(-I)
默认情况下,traceroute 发送的是 UDP(用户数据报协议)探测包,但有些路由器会屏蔽UDP包。换成ICMP模式通常能绕过这个问题。
# 使用ICMP模式发送探测包(类似ping,穿透性更好)
sudo traceroute -I www.example.com
注意 -I 模式需要 root 权限,因为发送原始ICMP包需要特权。这也是我日常工作最常用的模式,因为很多网络设备默认允许ICMP通过。
使用TCP模式(-T)
有些网络环境甚至ICMP也被屏蔽了,这时候可以试试TCP(传输控制协议)模式,模拟普通Web访问的流量。
# 使用TCP SYN包探测(类似浏览器发起的连接请求)
sudo traceroute -T -p 80 www.example.com
-p 80 指定目标端口为80(HTTP服务默认端口)。这个模式也适合检查某个特定端口的路由是否通。比如一台服务器的SSH(安全外壳协议,默认端口22)连不上,你可以用TCP模式追踪22端口的路由来排查。
不解析主机名(-n)
默认情况下traceroute会尝试把每一跳的IP反向解析成主机名,这会增加耗时。当你只关心延迟和路径时,可以用 -n 跳过解析。
# 不解析主机名,直接显示IP地址,速度更快
traceroute -n www.example.com
这在批量排查时很实用。有一次我需要验证公司到全国多个节点的网络质量,加上 -n 后整个脚本的执行时间减少了30%以上。
mtr:实时路由加延迟统计
mtr 的优势在于它把 traceroute 和 ping 结合起来了。它会持续探测每一跳,动态更新丢包率和延迟数据,让你可以实时看到网络抖动。
# 安装 mtr
sudo apt install mtr # Debian/Ubuntu
sudo yum install mtr # CentOS/RHEL
# 开始实时追踪目标主机
mtr www.example.com
启动后会进入一个交互式终端界面,每行显示一跳的信息,包括:
- ·Loss%:丢包率百分比
- ·Snt:已发送的探测包数量
- ·Last:最近一次探测的延迟
- ·Avg:平均延迟
- ·Best:最佳延迟(最低)
- ·Wrst:最差延迟(最高)
- ·StDev:延迟标准差,值越大说明延迟越不稳定
在交互界面中,按 q 退出,按 p 暂停/继续刷新,按 h 查看帮助。
使用mtr时有一个坑需要留意:如果中间某跳丢包但在下一跳不丢包,那这个丢包可能只是该路由器限制了ICMP回复速率,不代表实际数据包丢失。只有某跳丢包且后续所有跳都跟着丢包,那才是真正的链路问题。
# 只显示IP地址,不解析主机名
mtr -n www.example.com
# 指定探测包数量后自动退出(不进入交互界面)
mtr -n -c 10 www.example.com
-c 10 表示发送10个探测包后自动退出。这个参数在脚本里很好用,可以控制每次检测的时长。
mtr -r报告模式
把mtr输出用于报告或日志时,需要文本格式的输出而非交互界面。
# 报告模式,适合输出到文件或脚本
mtr -r -c 50 www.example.com
# 报告模式下只显示IP地址
mtr -r -n -c 50 www.example.com
# 指定报告轮数(每次探测发射的包数)
mtr -r -c 50 --report-wide www.example.com
--report-wide 会在输出中显示完整的主机名,不会被截断。在实际工作中,我经常把这条命令放到定时任务里,每隔几分钟跑一次,输出追加到日志文件。当用户报告网络问题时,翻出日志就能看到问题时段的网络状况。
# 写一个简单的监控脚本,每5分钟记录一次网络状态
# 先将要监控的目标写入文件
echo "www.example.com" > /tmp/targets.txt
# 用脚本循环检测
for target in $(cat /tmp/targets.txt); do
echo "===== $(date) - 检测 $target =====" >> /var/log/mtr-monitor.log
mtr -r -n -c 20 $target >> /var/log/mtr-monitor.log 2>&1
done
如何判断问题出在哪一跳
这是排查网络质量问题最核心的部分。看mtr的输出时,遵循以下原则:
第一,如果第一跳(通常是你的网关或者路由器的LAN口)就出现了高延迟或丢包,问题很可能出在你的内网环境。检查网线、WiFi信号或者本地路由器负载。
第二,如果前三跳(通常是宽带接入设备和运营商接入层设备)正常,但从某一跳开始延迟突然飙升,这就是主干网的问题。可能是运营商骨干网拥堵,也可能是某台老旧路由器不堪重负。
第三,如果目标是云服务,最后几跳通常是云服务商的边界网关或负载均衡器。这些设备通常有速率限制策略,少量丢包是正常的,但如果持续超过5%就不正常了。
曾经有一个案例,用户的视频会议总是卡顿。我用mtr跑了5分钟,发现有一跳的延迟在200ms到800ms之间剧烈波动,标准差(StDev)高达150以上。这个网络抖动就是会议卡顿的元凶,而问题出在运营商的一台老旧路由器上,更换硬件后问题解决。
traceroute和mtr的安全提醒
第一,traceroute和mtr的探测行为本质上是在探测网络结构。未经授权的大规模路由探测可能会被网络安全团队判定为侦察行为。在自己的网络环境中使用没问题,但在客户网络或公共网络上进行扫描式操作前,要先获得授权。
第二,sudo traceroute -I 和 sudo mtr 需要root权限。不要在不明来源的脚本中以root身份运行此类命令,防止被恶意利用。
第三,持续使用mtr会产生持续的网络流量。-c 参数可以控制探测次数,避免长时间运行时产生不必要的流量消耗。特别是在移动网络或计费网络环境下,注意控制探测频率。
第四,使用mtr的交互模式时,按 r 键会重新排序或整理显示,按 d 键可以切换显示模式。如果不小心改了显示布局,按 q 退出重开即可,不会影响系统。
总结
traceroute 和 mtr 是网络排查最重要的两款工具。traceroute 适合一次性快速追踪路由路径,mtr 则更适合持续观察网络质量。我个人的习惯是:先快速 traceroute 确认路径是否正常,如果发现异常再用 mtr 持续观察获取更多数据。
很多运维老手有句经验之谈:网络慢了不要慌,mtr跑五分钟再说。这话虽然朴实,但在实际工作中确实能解决80%以上的网络排查工作。
相关阅读
- ·
man traceroute:参数大全,特别是各种探测模式的细节 - ·
man mtr:深入了解mtr的报告格式和统计原理 - ·
/usr/share/doc/mtr/:安装目录下的文档,包含使用范例