大数跨境

Linux网络丢包?从排查到优化,这篇彻底讲清楚了!

Linux网络丢包?从排查到优化,这篇彻底讲清楚了! 河北镌远网络科技有限公司
2025-08-29
2
导读:深入分析Linux网络丢包

 深入分析Linux网络丢包

1、背景:


从图中可以看出,丢包可能发生在网络协议栈的全过程。具体来说:

  • 两台 VM 连接之间可能因网络拥塞、线路错误等导致传输失败。
  • 网卡接收数据后,环形缓冲区 (Ring Buffer) 可能因溢出而丢包。
  • 在链路层,网络帧校验失败、QoS 策略等可能导致丢包。
  • 在 IP 层,路由失败、分组大小超过 MTU 等可能导致丢包。
  • 在传输层,端口未监听、资源占用超过内核限制等可能导致丢包。
  • 在套接字层,套接字缓冲区溢出可能导致丢包。
  • 在应用层,应用程序异常可能导致丢包。
  • 此外,配置的 iptables 规则也可能因过滤而丢弃网络包。

2、链路层

当链路层(如缓冲区溢出)导致网卡丢包时,Linux 会在网卡统计信息中记录错误。可通过 ethtool 或 netstat -i 查看丢包记录:
   

关键指标:

  • RX-OK / TX-OK:

     成功接收/发送的总包数。
  • RX-ERR / TX-ERR:

     接收/发送错误总数。
  • RX-DRP / TX-DRP:

     进入 Ring Buffer 后因内存不足等原因导致的丢包数。
  • RX-OVR / TX-OVR:

     Ring Buffer 溢出导致的丢包数。

本例中未发现错误。注意: 使用 tc 等工具配置 QoS 导致的丢包不包含在网卡统计中。需检查 eth0 的 tc 规则及丢包统计:


结果显示 eth0 配置了网络模拟排队规则 (qdisc netem) 并设置丢包率为 30%。统计信息证实发送了 8 个包,丢弃了 4 个。这可能是 Nginx 响应包被丢弃的原因。

解决方案: 删除 netem 模块。


删除后,再次测试 (hping3 -c 10 -S -p 80 192.168.0.30) 显示仍有 50% 丢包和 RTT 波动。因此,需继续排查上层协议。

不幸的是,从 hping3 的输出中可以看到还是 50% 的丢包,RTT 的波动也仍旧很大,从 3ms 到 1s。显然,问题还是没解决,丢包还在继续发生。不过,既然链路层已经排查完了,我们就继续向上层分析,看看网络层和传输层有没有问题。


3、网络层和传输层

网络层和传输层引发丢包的因素众多。netstat -s 命令可查看各协议汇总统计和错误信息,快速确认丢包情况:

etstat 汇总了 IP、ICMP、TCP、UDP 等各种协议的收发统计信息。不过,我们的目的是排查丢包问题,所以这里主要观察的是错误数、丢包数以及重传数。可以看到,只有 TCP 协议发生了丢包和重传,分别是:

  • 11 failed connection attempts

    : 连接失败重试。
  • 4 segments retransmitted

    : 报文重传。
  • 11 resets received for embryonic SYN_RECV sockets

    : 半连接重置(三次握手未完成)。
  • TCPSynRetrans: 4

    : SYN 包重传。
  • TCPTimeouts: 7

    : 连接超时。

这些错误表明主要问题是三次握手失败。但根源仍需进一步分析。


4、iptables

iptables 规则和连接跟踪 (conntrack) 机制也可能导致丢包。

先来看看连接跟踪,要确认是不是连接跟踪导致的问题,只需要对比当前的连接跟踪数和最大连接跟踪数即可。


可以看到,连接跟踪数只有 182,而最大连接跟踪数则是 262144。显然,这里的丢包,不可能是连接跟踪导致的。

接着,再来看 iptables。回顾一下 iptables 的原理,它基于 Netfilter 框架,通过一系列的规则,对网络数据包进行过滤(如防火墙)和修改(如 NAT)。这些 iptables 规则,统一管理在一系列的表中,包括 filter、nat、mangle(用于修改分组数据) 和 raw(用于原始数据包)等。而每张表又可以包括一系列的链,用于对 iptables 规则进行分组管理。

对于丢包问题来说,最大的可能就是被 filter 表中的规则给丢弃了。要弄清楚这一点,就需要我们确认,那些目标为 DROP 和 REJECT 等会弃包的规则,有没有被执行到。可以直接查询 DROP 和 REJECT 等规则的统计信息,看看是否为0。如果不是 0 ,再把相关的规则拎出来进行分析。


从 iptables 的输出中,你可以看到,两条 DROP 规则的统计数值不是 0,它们分别在INPUT 和 OUTPUT 链中。这两条规则实际上是一样的,指的是使用 statistic 模块,进行随机 30% 的丢包。0.0.0.0/0 表示匹配所有的源 IP 和目的 IP,也就是会对所有包都进行随机 30% 的丢包。看起来,这应该就是导致部分丢包的“罪魁祸首”了。

执行下面的两条 iptables 命令,删除这两条 DROP 规则。


再次执行刚才的 hping3 命令,看看现在是否正常



不过,到目前为止,我们一直使用的 hping3 工具,只能验证案例 Nginx 的 80 端口处于正常监听状态,却还没有访问 Nginx 的 HTTP 服务。所以,不要匆忙下结论结束这次优化,我们还需要进一步确认,Nginx 能不能正常响应 HTTP 请求。我们继续在终端二中,执行如下的 curl 命令,检查 Nginx 对 HTTP 请求的响应:


奇怪,hping3 的结果显示Nginx 的 80 端口是正常状态,为什么还是不能正常响应 HTTP 请求呢?别忘了,我们还有个大杀器——抓包操作。看来有必要抓包看看了。


5、tcpdump

执行下面的 tcpdump 命令,抓取 80 端口的包


然后,切换到终端二中,再次执行前面的 curl 命令:

在这里插入图片描述

可以重新执行 netstat -i 命令,确认一下网卡有没有丢包问题:

从 netstat 的输出中,你可以看到,接收丢包数(RX-DRP)是 344,果然是在网卡接收时丢包了。不过问题也来了,为什么刚才用 hping3 时不丢包,现在换成 GET 就收不到了呢?还是那句话,遇到搞不懂的现象,不妨先去查查工具和方法的原理。我们可以对比一下这两个工具:

  • • hping3 实际上只发送了 SYN 包;
  • • curl 在发送 SYN 包后,还会发送 HTTP GET 请求。HTTP GET本质上也是一个 TCP 包,但跟 SYN 包相比,它还携带了 HTTP GET 的数据。

通过这个对比,你应该想到了,这可能是 MTU 配置错误导致的。为什么呢?

其实,仔细观察上面 netstat 的输出界面,第二列正是每个网卡的 MTU 值。eth0 的 MTU只有 100,而以太网的 MTU 默认值是 1500,这个 100 就显得太小了。当然,MTU 问题是很好解决的,把它改成 1500 就可以了。

ifconfig eth0 mtu 1500

文章来源:网络

公众号“河北镌远网络科技有限公司”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,小编会第一时间删除处理。




【声明】内容源于网络
0
0
河北镌远网络科技有限公司
河北镌远网络科技有限公司是一家集人才、经验、技术于一体的,提供全面系统集成解决方案的专业IT服务商。公司致力于为各个行业的业务信息化提供软件和通用解决方案、系统架构,系统管理和数据安全服务、以及IT咨询规划、系统集成与系统服务等专业化服务。
内容 0
粉丝 0
河北镌远网络科技有限公司 河北镌远网络科技有限公司是一家集人才、经验、技术于一体的,提供全面系统集成解决方案的专业IT服务商。公司致力于为各个行业的业务信息化提供软件和通用解决方案、系统架构,系统管理和数据安全服务、以及IT咨询规划、系统集成与系统服务等专业化服务。
总阅读0
粉丝0
内容0