本文主要介绍可能引起云服务器网络访问丢包问题的可能原因及对应解决方法。
可能原因
引起云服务器网络访问丢包问题的可能原因如下:
可能原因 | 处理措施 |
触发限速导致 TCP 丢包 | |
触发限速导致 UDP 丢包 | |
触发软中断丢包 | |
UDP 发送缓冲区满导致丢包 | |
UDP 接收缓冲区满 | |
TCP 全连接队列满导致丢包 | |
TCP 请求溢出导致丢包 | |
连接数达到上限导致丢包 | |
iptables policy 设置的规则导致丢包 | |
firewalld 是否开启 |
故障处理
检查是否触发限速导致 TCP 丢包
云服务器实例具备多种规格,且不同规格有不同的网络性能。当实例的带宽或包量超过实例规格对应的标准时,会触发平台侧的限速,导致丢包。排查及处理步骤如下:
1. 查看实例的带宽及包量。
Linux 实例可执行
sar -n DEV 2
命令查看带宽及包量。其中,rxpck/s
和 txpck/s
指标是收发包量,rxkB/s
和 txkB/s
指标是收发带宽。2. 使用获取的带宽及包量数据对比 实例规格,查看是否达到实例规格性能瓶颈。
若已达到实例规格性能瓶颈,则需升级实例规格或调整业务量。
若未达到实例规格性能瓶颈,则可通过 在线支持 进一步定位处理。
检查是否触发限速导致 UDP 丢包
是否由实例规格性能瓶颈引起丢包,则需升级实例规格或调整业务量。
若未达到实例规格性能瓶颈,则可能是由平台对 DNS 请求额外的频率限制引起。在实例整体带宽或包量达到实例规格的性能瓶颈时,可能会触发 DNS 请求限速而出现 UDP 丢包。可通过 在线支持 进一步定位处理。
检查是否触发软中断丢包
当操作系统检测到
/proc/net/softnet_stat
的第二列计数值在增长时,则会判断为“软中断丢包”。当您的实例触发了软中断丢包时,可通过以下步骤进行排查及处理:
查看是否开启 RPS:开启,则内核参数
net.core.netdev_max_backlog
偏小时会引发丢包,需调大。内核参数详细信息请参见 Linux 实例常用内核参数介绍。未开启,则查看是否为 CPU 单核软中断高,导致未能及时收发数据。若是,您可以:
选择开启 RPS,使软中断分配更为均衡。
检查业务程序是否会引发软中断分配不均匀。
检查是否 UDP 发送缓冲区满导致丢包
若您的实例因 UDP 发送缓冲区不足而导致丢包时,可通过以下步骤进行排查处理:
1. 使用
nstat
命令来查看 UDP 相关的统计信息。您可以通过 nstat | grep Udp
来查看与 UDP 有关的统计。以下是其中一些有关的参数及含义:
UdpInDatagrams:已接收的 UDP 数据包数量
UdpNoPorts:没有任何端口接收的 UDP 数据包数量
UdpInErrors:因数据包错误(如数据包长度错误,IP 校验和错误等)而不能交付的 UDP 数据包数量。
UdpOutDatagrams:已发送的 UDP 数据包数量
UdpRcvbufErrors:由于接收缓冲区满而不能接收的 UDP 数据包数量
UdpSndbufErrors:由于发送缓冲区满而不能发送的 UDP 数据包数量
2. 重点关注
UdpSndbufErrors
字段,该字段表示由于发送缓冲区满而不能发送的 UDP 数据包数量。如果该值较高或者持续增加,可能就是因为 UDP 发送缓冲区满而导致的丢包。3. 如果
UdpSndbufErrors
字段较高或者持续增加,您可以尝试通过调大内核参数 net.core.wmem_max
和 net.core.wmem_default
来增加发送缓冲区的大小,并重启 UDP 程序以生效。具体如何调整内核参数可以参见 Linux 实例常用内核参数介绍。4. 验证发送缓冲区大小是否调整成功,执行
ss -nump
命令查看 UDP 的状态信息,该命令会显示出各个 UDP socket 的详细信息。输出中的部分信息如
skmem:(r0 ,rb62914560,t0,tb62914560,f0,w0,o0,bl0)
表明 socket 的内存使用情况,部分字段具体含义如下:r: 已接收但还未读取的字节数(receive queue)
rb: 接收缓冲区大小 (receive buffer size)
t: 发送队列中等待发送的数据的字节数(send queue)
tb: 发送缓冲区大小 (send buffer size)
确认发送缓冲区是否符合预期。
5. 若调整后仍存在丢包问题,再次使用
nstat | grep UdpSndbufErrors
命令查看 UdpSndbufErrors
字段,看其是否仍持续增加。若是,您需要检查业务代码是否通过 setsockopt
设置了 SO_SNDBUF
。如果已设置,您可能需要修改代码来增大 SO_SNDBUF 值。虽然您可以通过修改 net.core.wmem_max
和 net.core.wmem_default
参数来尝试增大发送缓冲区的大小,但是如果程序中 SO_SNDBUF 设置得过小,无论系统级别的缓冲区大小如何,都可能会因为此限制导致发送缓冲区满。检查是否 UDP 接收缓冲区满导致丢包
若您的实例因 UDP 接收缓冲区不足而导致丢包时,可通过以下步骤进行排查处理:
1. 参见检查是否 UDP 发送缓冲区满导致丢包步骤,用
nstat
命令检查 UdpRcvbufErrors
字段。该字段表示由于接收缓冲区满而不能接收的 UDP 数据包数量。如果该值较高或者持续增加,可能是因为 UDP 接收缓冲区满而导致的丢包。2. 如果
UdpRcvbufErrors
字段较高或者持续增加,您可以尝试通过调大内核参数 net.core.rmem_max
和 net.core.rmem_default
来增加接收缓冲区的大小,并重启 UDP 程序以生效。具体如何调整内核参数可以参见 Linux 实例常用内核参数介绍。3. 验证接收缓冲区大小是否调整成功,执行
ss -nump
命令查看 rb: 接收缓冲区大小 (receive buffer size),确认接收缓冲区是否符合预期。4. 若调整后仍存在丢包问题,再次使用
nstat | grep UdpRcvbufErrors
命令查看 UdpRcvbufErrors
字段,看其是否仍持续增加。若是,您需要检查 业务代码是否通过setsockopt
设置了 SO_RCVBUF。如果设置了,您可能需要修改代码来增大 SO_RCVBUF 值。这是因为虽然我们可以通过修改net.core.rmem_max
和 net.core.rmem_default
参数来尝试增大接收缓冲区的大小,但是如果程序中 SO_RCVBUF设置得过小,那么无论系统级别的缓冲区大小如何,都可能会因为这个限制导致接收缓冲区满。检查是否 TCP 全连接队列满导致丢包
当您的实例发生 TCP 全连接队列满导致丢包时,优先检查业务应用是否处理延迟过大,业务进程 CPU 使用率是否过高,造成无法及时接收新连接。
若已确认业务进程 CPU 使用率及处理延迟都较低,可以检查是否属于以下常见 Case:
1. 打开文件数目达到限制,可能会造成业务进程 Accept 失败,从而无法正常处理新增连接。这种情况,一般来说,系统日志里会有 Too many open files 的报错。注意,调整 open file 相关限制的时候,需要检查
/etc/security/limits.conf
中针对用户级别的限制和内核参数 fs.file-nr 针对系统级别的限制两个方面。2. 业务层面负责处理新增连接的线程数有限制。常见于 Java 类业务。需要从业务层面调整线程数。
若不属于以上常见 Case,可尝试按以下步骤调整参数,以应对可能的请求突发造成的全连队列满丢包:
1. 调大内核参数
net.core.somaxconn
。内核参数详细信息请参见 Linux 实例常用内核参数介绍。2. 检查业务进程是否传入了 backlog 参数。若是,则相应调大。
检查是否 TCP 请求溢出导致丢包
在 TCP 接收数据时,若 socket 被 user 锁住,则会将数据送到 backlog 队列。若此过程失败,则会引起 TCP 请求溢出导致丢包。通常情况下,假设业务程序性能正常,则可参见以下方式从系统层面排查及处理问题:
检查业务程序是否通过 setsockopt 自行设置了 buffer 大小:
若已设置,且该值不够大,可以修改业务程序指定一个更大的值,或不再通过 setsockopt 指定大小。
说明
setsockopt 的取值受内核参数
net.core.rmem_max
和 net.core.wmem_max
限制。调整业务程序的同时,可以同步调整 net.core.rmem_max
和 net.core.wmem_max
。调整后请重启业务程序使配置生效。若未设置,则可以调大
net.ipv4.tcp_mem
、net.ipv4.tcp_rmem
和 net.ipv4.tcp_wmem
内核参数来调整 TCP socket 的水位。
内核参数修改请参见 Linux 实例常用内核参数介绍。检查是否连接数达到上限导致丢包
云服务器实例具备多种规格,且不同规格有不同的连接数性能指标。当实例的连接数超过实例规格对应的标准时,会触发平台的限速,导致丢包。处理步骤如下:
说明
连接数指宿主机上保存的云服务器实例的会话数,包含 TCP、UDP 和 ICMP。该数值大于在云服务器实例上通过
ss
或 netstat
命令获取的网络连接数。若已达到实例规格性能瓶颈,则需升级实例规格或调整业务量。
若未达到实例规格性能瓶颈,则可通过 在线支持 进一步定位处理。
检查 iptables policy 设置的规则
在云服务器 iptables 未设置相关规则的情况下,可能是 iptables policy 相关规则设置导致到达云服务器的包都被丢弃。处理步骤如下:
1. 执行以下命令,查看 iptables policy 规则。
iptables -L | grep policy
iptables policy 规则默认为 ACCEPT。若 INPUT 链 policy 非 ACCEPT,则会导致所有到服务器的包都被丢弃。例如,若返回如下结果,表示进入云服务器的包都会被 drop。
Chain INPUT (policy DROP)Chain FORWARD (policy ACCEPT)Chain OUTPUT (policy ACCEPT)
2. 执行如下命令,按需调整
-P
后的值。iptables -P INPUT ACCEPT
Chain INPUT (policy ACCEPT)Chain FORWARD (policy ACCEPT)Chain OUTPUT (policy ACCEPT)
检查 firewalld 是否开启
在使用云服务器时,可能会遇到网络连接问题,这可能是由于防火墙(firewalld)设置不当导致的。在进行故障排查时,首先需要检查 firewalld 是否启动,然后确认规则是否是自己添加的还是误操作增加的,最后可以考虑关闭 firewalld。以下是详细的检查和处理步骤:
1. 确认 firewalld 是否启动, 执行以下命令,查看 firewalld 状态,如果 firewalld 已启动,输出结果会显示 active (running),则继续检查。如果 firewalld 未启动,说明不是 firewalld 导致的问题,则不需要继续流程。
systemctl status firewalld
2. 使用
iptables -nvL
命令检查防火墙规则,通过查看输出结果,可以确认是否有自己添加的规则或误操作添加的规则。iptables -nvL
3. 关闭 firewalld。
如果确认规则是误操作添加的,可以先关闭 firewalld 后观察是否正常。执行以下命令关闭 firewalld。
systemctl stop firewalld
通过以上步骤,可以排查并解决由于 firewalld 设置不当导致的网络连接问题。在进行配置调整时,请务必谨慎操作,以免影响服务器的正常运行。