用 mtr 定位丢包位置:若仅末跳丢包,多为服务端问题;若中间某跳持续高丢包,则锁定该网络设备;需结合 tcping 验证端口、netstat -i 查 RX-OVR/RX-DRP、tc qdisc 检查 netem 丢包、iptables/conntrack 排查内核过滤、tcpdump 抓包确认是否入栈、ss -i 分析套接字层接收队列堆积。
先确认丢包真实存在,且不是本地或远端单点问题。直接 ping 只能告诉你“有没有丢”,但没法说清“在哪丢”。这时候必须上 mtr——它一边 traceroute 逐跳探测,一边持续 ping 每一跳,输出里每行的 Loss% 就是关键证据。
??? 或高 Loss% 是假阳性,需结合 tcping -x 5 www.example.com 443 验证业务端口是否真不通netstat -i 输出里的 RX-OVR(Ring Buffer 溢出)常被当作“网卡扛不住”的铁证,但现实更复杂:它只反映驱动层 Ring Buffer 满了之后丢包,不包括后续协议栈各层丢弃。更隐蔽的是——tc qdisc 配置的丢包(比如 netem loss 30%)完全不会出现在这里。
netstat -i,重点看 RX-DRP(进缓冲区后因内存不足等丢)和 RX-OVR 是否持续增长tc qdisc show dev eth0,尤其留意含 loss、limit、delay 的 netem 规则ethtool -S eth0 | grep -i "drop\|overrun" 可看到更底层硬件计数,但虚拟网卡(如 virtio)这些字段常为 0,不可全信很多丢包根本不是网络问题,而是被内核“主动杀掉”了。iptables 的 DROP 规则不记日志时,包就静默消失;更麻烦的是连接跟踪(conntrack)满表导致新连接 SYN 包被丢,现象和网络中断一模一样。
iptables -P INPUT ACCEPT; iptables -P FORWARD ACCEPT; iptables -F(操作后务必恢复)conntrack -S 看 entries 是否接近 max,再用 sysctl net.netfilter.nf_conntrack_max 确认上限tcpdump -i eth0 -n 'host 192.168.0.30 and port 80'。如果 tcpdump 没抓到包,但 mtr 显示最后一跳通——说明包压根没进本机,问题在链路或对端防火墙当 TCP 连接已建立但数据收发异常,netstat -s | grep -i "retransmit\|drop" 只给汇总值,无法定位具体 socket。而 ss -i 能显示每个连接的重传、SACK、接收队列溢出(rcv_space vs rcv_rtt)等实时指标。
ss -tin
state established '( dport = :80 )' | head -10,关注 skw(发送队列)、skr(接收队列)和 rcv_space
skr 接近 rcv_space 且持续不降,说明应用读取太慢,内核被迫丢后续包(TCP RcvQ Full 类丢包)ss -s 中 packets received 和 with invalid CSUM 差值,可粗略估算校验失败丢包比例真正难缠的丢包,往往藏在“看似正常”的环节里:tc 规则无声无息吃掉 30% 包,conntrack 表满导致新连接永远卡在 SYN_RCVD,甚至应用层 recv() 调用太慢,让内核在套接字缓冲区就把包扔了——这些都不会在 ping 或 ifconfig 里报错,必须一层层剥开协议栈验证。