当前位置:首页 > 娱乐

linux查线路丢包

上周三下午,线路运维群里有人甩了张监控截图,丢包一台跑着Nginx的线路边缘节点,到上游Redis集群的丢包丢包率飙到了7%。第一反应是线路网络抖动,但同机房其他机器没事。丢包这就不是线路交换机或者光模块的锅了,问题大概率出在这台机器自己身上。丢包

查丢包,线路我习惯从底层往上捋。丢包先看网卡,线路ip -s link show eth0,丢包RX errors和dropped字段如果非零,线路那基本就是丢包驱动、缓冲区或者硬件层面的线路问题。那次这台机器RX dropped有几千,但errors是0。dropped高通常意味着环形缓冲区满了,包到了网卡但内核没来得及收。用ethtool -S eth0 | grep -i drop能看得更细,比如rx_fifo_errors或者rx_missed_errors。当时rx_missed_errors在涨,说明网卡FIFO溢出,中断处理跟不上。查了一下,这台机器开了irqbalance但网卡中断全绑在CPU0上,其他核在围观。手动把中断分散到多个核,丢包立刻掉到0.3%。

但丢包不一定在网卡。如果ip -s link干干净净,那就往上走,看协议栈。最直接的工具是netstat -su,UDP的接收错误和发送错误会直接列出来。TCP的话看netstat -st,重传和超时计数能反映问题。有一次我碰到一个诡异情况:应用层日志报连接超时,但网卡和协议栈统计都正常。最后用ss -ti看单个连接的细节,发现retrans字段在涨,而rtt波动极大。原因是那台机器开了TCP BBR,但中间有个老防火墙对BBR的 pacing 行为不友好,导致大量重传。换回 cubic 就稳了。

再往上,就是防火墙和路由。iptables 的 -j DROP 规则不会在网卡统计里体现,但会在 nf_conntrack 或者自定义链的计数器里。用 iptables -L -v -n 看每条规则的包计数,如果某条DROP规则在涨,那就是它干的。有次一台机器丢包,查了半天发现是之前有人加了条限速规则,把来自某个网段的包给限了,但没写注释,坑了整个团队两天。

路由问题更隐蔽。ip route get 目标IP 能看实际走哪条路。如果路由表里有多个默认网关,或者策略路由配错了,包可能从错误的接口出去,然后被对端丢弃。我见过一个案例:两台机器在同一个子网,但一台配了 rp_filter=1,另一台的回包源地址被路由到了别的接口,结果入方向被反向路径过滤给丢了。关掉 rp_filter 或者修正路由就解决了。

还有一类丢包来自内核的 netdev_max_backlog。这个队列是网卡收包后、协议栈处理前的缓冲。默认1000,在高PPS场景下很容易满。用 cat /proc/net/softnet_stat 看第二列,如果数字在涨,说明软中断处理不过来,包被丢了。调大这个值,或者开RPS/RFS把软中断分散到多核,能缓解。

工具链上,mtr 比 traceroute 好用,它能持续显示每跳的丢包率。但注意,中间跳的丢包不一定是真丢,可能是ICMP限速。看最后一跳的丢包才有意义。tcpdump 抓包对比两端,能定位是发出去没到,还是到了没回。有次我抓包发现SYN发出去了,对端也回了SYN-ACK,但本机没收到。查 arp -n 发现网关的MAC地址是错的,被静态ARP绑死了。这种问题,ip -s neigh 里的 FAILED 状态会暴露。

最后说个反直觉的:丢包不一定是网络问题。应用层自己丢包,比如socket缓冲区设太小,或者用了 SO_RCVBUF 但没调大,内核收包后没地方放,也会丢。用 ss -m 看socket的内存使用,skmem 字段里的 r 和 w 如果接近上限,那就是应用没及时读。这种丢包,网卡和协议栈统计都正常,但业务就是收不到。

查丢包这事,没有银弹。从 ip -s link 到 ss -ti,再到 tcpdump 和 mtr,每一步都在缩小范围。关键是别跳过底层直接猜应用,也别死盯着一个工具。数据不会骗人,但得知道去哪找。

分享到: