服务器总是时不时丢包,我该怎么办?(上)
nanshan 2024-10-27 11:19 32 浏览 0 评论
目录
案例准备
案例分析
启动项目
模拟访问并观察丢包情况
3s 的 RTT -很可能是因为丢包后重传导致的
链路层(ethtool 或者 netstat)
网络层和传输层
所谓丢包,是指在网络数据的收发过程中,由于种种原因,数据包还没传输到应用程序中,就被丢弃了。这些被丢弃包的数量,除以总的传输包数,也就是我们常说的丢包率。丢包率是网络性能中最核心的指标之一。
丢包通常会带来严重的性能下降,特别是对 TCP 来说,丢包通常意味着网络拥塞和重传,进而还会导致网络延迟增大、吞吐降低。
案例准备
今天的案例需要用到两台虚拟机。
使用vagrant拉起两台虚机。
- 机器配置:2 CPU,2GB 内存。
- 预先安装 docker、curl、hping3 等工具
案例分析
我们今天要分析的案例是一个 Nginx 应用,如下图所示,hping3 和 curl 是 Nginx 的客户端。
我这里对应的ip是192.168.56.10 和192.168.56.11
?
启动项目
[root@hadoop100 /opt]#docker run --name nginx --hostname nginx --privileged -p 80:80 -itd feisky/nginx:drop
Unable to find image 'feisky/nginx:drop' locally
drop: Pulling from feisky/nginx
6ae821421a7d: Pull complete
da4474e5966c: Pull complete
eb2aec2b9c9f: Pull complete
c6797838e67f: Pull complete
d61fc363525d: Pull complete
Digest: sha256:c16b8286464e50b4c9704ed83e3e111f9c19a60f4ceca775d752b4bd0108637f
Status: Downloaded newer image for feisky/nginx:drop
5867df6e997b047bf995ade980f0db0206bec2df1d9e8738bef415c55c55bb71
You have mail in /var/spool/mail/root
[root@hadoop100 /opt]#
[root@hadoop100 /opt]#
[root@hadoop100 /opt]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5867df6e997b feisky/nginx:drop "/start.sh" 43 seconds ago Up 42 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx
模拟访问并观察丢包情况
我们切换到终端二中,执行下面的 hping3 命令,进一步验证 Nginx 是不是真的可以正常访问了。注意,这里我没有使用 ping,是因为 ping 基于 ICMP 协议,而 Nginx 使用的是 TCP 协议。
- -c 表示发送 20 个请求
- -S 表示使用 TCP SYN
- -p 指定端口为 80
[root@hadoop101 yum.repos.d]# hping3 -c 20 -S -p 80 192.168.56.10
HPING 192.168.56.10 (eth1 192.168.56.10): S set, 40 headers + 0 data bytes
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=1 win=5120 rtt=1201.8 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=4 win=5120 rtt=1.9 ms
DUP! len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=4 win=5120 rtt=1002.7 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=5 win=5120 rtt=1.4 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=9 win=5120 rtt=0.9 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=10 win=5120 rtt=0.8 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=11 win=5120 rtt=0.8 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=12 win=5120 rtt=1.9 ms
len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=13 win=5120 rtt=0.9 ms
DUP! len=46 ip=192.168.56.10 ttl=63 DF id=0 sport=80 flags=SA seq=10 win=5120 rtt=3204.2 ms
--- 192.168.56.10 hping statistic ---
20 packets transmitted, 10 packets received, 50% packet loss
round-trip min/avg/max = 0.8/541.7/3204.2 ms
从 hping3 的输出中,我们可以发现,发送了 20 个请求包,却只收到了 10 个回复,50% 的包都丢了。再观察每个请求的 RTT 可以发现,RTT 也有非常大的波动变化,小的时候只有 1ms,而大的时候则有 3s。
3s 的 RTT -很可能是因为丢包后重传导致的
根据这些输出,我们基本能判断,已经发生了丢包现象。可以猜测,3s 的 RTT ,很可能是因为丢包后重传导致的。那到底是哪里发生了丢包呢?
排查之前,我们可以回忆一下 Linux 的网络收发流程,先从理论上分析,哪里有可能会发生丢包。你不妨拿出手边的笔和纸,边回忆边在纸上梳理,思考清楚再继续下面的内容。
?
从图中你可以看出,可能发生丢包的位置,实际上贯穿了整个网络协议栈。换句话说,全程都有丢包的可能。比如我们从下往上看:
- 在两台 VM 连接之间,可能会发生传输失败的错误,比如网络拥塞、线路错误等;
- 在网卡收包后,环形缓冲区可能会因为溢出而丢包;
- 在链路层,可能会因为网络帧校验失败、QoS 等而丢包;
- 在 IP 层,可能会因为路由失败、组包大小超过 MTU 等而丢包;
- 在传输层,可能会因为端口未监听、资源占用超过内核限制等而丢包;
- 在套接字层,可能会因为套接字缓冲区溢出而丢包;
- 在应用层,可能会因为应用程序异常而丢包;
- 此外,如果配置了 iptables 规则,这些网络包也可能因为 iptables 过滤规则而丢包。
当然,上面这些问题,还有可能同时发生在通信的两台机器中。不过,由于我们没对 VM2 做任何修改,并且 VM2 也只运行了一个最简单的 hping3 命令,这儿不妨假设它是没有问题的。
为了简化整个排查过程,我们还可以进一步假设, VM1 的网络和内核配置也没问题。这样一来,有可能发生问题的位置,就都在容器内部了。
现在我们切换回终端一,执行下面的命令,进入容器的终端中:
链路层(ethtool 或者 netstat)
首先,来看最底下的链路层。当缓冲区溢出等原因导致网卡丢包时,Linux 会在网卡收发数据的统计信息中,记录下收发错误的次数。
你可以通过 ethtool 或者 netstat ,来查看网卡的丢包记录。
[root@hadoop100 /usr/local/src/sysstat-11.5.5]#docker exec -it nginx bash
root@nginx:/#
root@nginx:/#
root@nginx:/# netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 100 58 0 0 0 19 0 0 0 BMRU
lo 65536 0 0 0 0 0 0 0 0 LRU
输出中的 RX-OK、RX-ERR、RX-DRP、RX-OVR ,分别表示接收时的总包数、总错误数、进入 Ring Buffer 后因其他原因(如内存不足)导致的丢包数以及 Ring Buffer 溢出导致的丢包数。
TX-OK、TX-ERR、TX-DRP、TX-OVR 也代表类似的含义,只不过是指发送时对应的各个指标。
注意,由于 Docker 容器的虚拟网卡,实际上是一对 veth pair,一端接入容器中用作 eth0,另一端在主机中接入 docker0 网桥中。veth 驱动并没有实现网络统计的功能,所以使用 ethtool -S 命令,无法得到网卡收发数据的汇总信息。
从这个输出中,我们没有发现任何错误,说明容器的虚拟网卡没有丢包。不过要注意,如果用 tc 等工具配置了 QoS,那么 tc 规则导致的丢包,就不会包含在网卡的统计信息中。
所以接下来,我们还要检查一下 eth0 上是否配置了 tc (traffic control)规则,并查看有没有丢包。我们继续容器终端中,执行下面的 tc 命令,不过这次注意添加 -s 选项,以输出统计信息:
root@nginx:/#
root@nginx:/#
root@nginx:/# tc -s qdisc show dev eth0
qdisc netem 8001: root refcnt 2 limit 1000 loss 30%
Sent 1038 bytes 19 pkt (dropped 7, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
root@nginx:/#
什么是tc?
从 tc 的输出中可以看到, eth0 上面配置了一个网络模拟排队规则(qdisc netem),并且配置了丢包率为 30%(loss 30%)。
再看后面的统计信息,发送了 19个包,但是丢了 7 个。
看来,应该就是这里,导致 Nginx 回复的响应包,被 netem 模块给丢了。
既然发现了问题,解决方法也就很简单了,直接删掉 netem 模块就可以了。我们可以继续在容器终端中,执行下面的命令,删除 tc 中的 netem 模块:
#注意是容器内部
root@nginx:/# tc qdisc del dev eth0 root netem loss 30%
root@nginx:/#
root@nginx:/#
root@nginx:/# tc -s qdisc show dev eth0
qdisc noqueue 0: root refcnt 2
Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
root@nginx:/#
重新执行刚才的 hping3 命令
?
从 hping3 的输出中,我们可以看到,跟前面现象一样,还是 40% 的丢包;RTT 的波动也仍旧很大,从 3ms 到 1s。
显然,问题还是没解决,丢包还在继续发生。不过,既然链路层已经排查完了,我们就继续向上层分析,看看网络层和传输层有没有问题。
网络层和传输层
我们知道,在网络层和传输层中,引发丢包的因素非常多。不过,其实想确认是否丢包,是非常简单的事,因为 Linux 已经为我们提供了各个协议的收发汇总情况。
我们继续在容器终端中,执行下面的 netstat -s 命令,就可以看到协议的收发汇总,以及错误信息了:
root@nginx:/# netstat -s
Ip:
Forwarding: 1 // 开启转发
31 total packets received // 总收包数
0 forwarded // 转发包数
0 incoming packets discarded // 接收丢包数
25 incoming packets delivered // 接收的数据包数
15 requests sent out // 发出的数据包数
Icmp:
0 ICMP messages received // 收到的 ICMP 包数
0 input ICMP message failed // 收到 ICMP 失败数
ICMP input histogram:
0 ICMP messages sent //ICMP 发送数
0 ICMP messages failed //ICMP 失败数
ICMP output histogram:
Tcp:
0 active connection openings // 主动连接数
0 passive connection openings // 被动连接数
11 failed connection attempts // 失败连接尝试数
0 connection resets received // 接收的连接重置数
0 connections established // 建立连接数
25 segments received // 已接收报文数
21 segments sent out // 已发送报文数
4 segments retransmitted // 重传报文数
0 bad segments received // 错误报文数
0 resets sent // 发出的连接重置数
Udp:
0 packets received
...
TcpExt:
11 resets received for embryonic SYN_RECV sockets // 半连接重置数
0 packet headers predicted
TCPTimeouts: 7 // 超时数
TCPSynRetrans: 4 //SYN 重传数
...
netstat 汇总了 IP、ICMP、TCP、UDP 等各种协议的收发统计信息。不过,我们的目的是排查丢包问题,所以这里主要观察的是错误数、丢包数以及重传数。
根据上面的输出,你可以看到,只有 TCP 协议发生了丢包和重传,分别是:
- 11 次连接失败重试(11 failed connection attempts)
- 4 次重传(4 segments retransmitted)
- 11 次半连接重置(11 resets received for embryonic SYN_RECV sockets)
- 4 次 SYN 重传(TCPSynRetrans)
- 7 次超时(TCPTimeouts)
这个结果告诉我们,TCP 协议有多次超时和失败重试,并且主要错误是半连接重置。换句话说,主要的失败,都是三次握手失败。
不过,虽然在这儿看到了这么多失败,但具体失败的根源还是无法确定。所以,我们还需要继续顺着协议栈来分析。接下来的几层又该如何分析呢?你不妨自己先来思考操作一下,下一节我们继续来一起探讨。
?
下面是生产环境的完整数据
/tmp]#netstat -s
Ip:
1683658515 total packets received
340 forwarded
0 incoming packets discarded
1683622451 incoming packets delivered
1728458438 requests sent out
9099056 outgoing packets dropped
Icmp:
49431231 ICMP messages received
83049 input ICMP message failed.
ICMP input histogram:
destination unreachable: 49206747
echo requests: 224460
echo replies: 24
49431231 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
destination unreachable: 49206747
echo request: 24
echo replies: 224460
IcmpMsg:
InType0: 24
InType3: 49206747
InType8: 224460
OutType0: 224460
OutType3: 49206747
OutType8: 24
Tcp:
78687674 active connections openings
15276116 passive connection openings
63172546 failed connection attempts
19791847 connection resets received
340 connections established
1553698421 segments received
1629613317 segments send out
108022 segments retransmited
0 bad segments received.
36033483 resets sent
Udp:
232938 packets received
49073844 packets to unknown port received.
0 packet receive errors
49307001 packets sent
UdpLite:
TcpExt:
114 invalid SYN cookies received
18 packets pruned from receive queue because of socket buffer overrun
12 ICMP packets dropped because they were out-of-window
30510 TCP sockets finished time wait in fast timer
8295195 TCP sockets finished time wait in slow timer
4 passive connections rejected because of time stamp
109534533 delayed acks sent
547 delayed acks further delayed because of locked socket
Quick ack mode was activated 6721 times
167267223 packets directly queued to recvmsg prequeue.
32026299 packets directly received from backlog
2449736681 packets directly received from prequeue
588917805 packets header predicted
7928866 packets header predicted and directly queued to user
142086396 acknowledgments not containing data received
814970084 predicted acknowledgments
3339 times recovered from packet loss due to SACK data
Detected reordering 1 times using FACK
Detected reordering 1 times using time stamp
4 congestion windows fully recovered
1 congestion windows partially recovered using Hoe heuristic
TCPDSACKUndo: 26
154 congestion windows recovered after partial ack
208 TCP data loss events
TCPLostRetransmit: 10
839 timeouts after SACK recovery
3 timeouts in loss state
4500 fast retransmits
1541 forward retransmits
371 retransmits in slow start
50763 other TCP timeouts
135 sack retransmits failed
3 times receiver scheduled too late for direct processing
8866 packets collapsed in receive queue due to low socket buffer
6736 DSACKs sent for old packets
343 DSACKs received
11929374 connections reset due to unexpected data
153421 connections reset due to early user close
70 connections aborted due to timeout
TCPDSACKIgnoredNoUndo: 158
TCPSackShifted: 1
TCPSackMerged: 463
TCPSackShiftFallback: 21108
TCPBacklogDrop: 1
TCPChallengeACK: 3570
TCPSYNChallenge: 1
TCPFromZeroWindowAdv: 287
TCPToZeroWindowAdv: 287
TCPWantZeroWindowAdv: 870914
IpExt:
InMcastPkts: 113809
InBcastPkts: 31073473
InOctets: 654459568091
OutOctets: 503387673001
InMcastOctets: 3641888
InBcastOctets: 3103324037
18 packets pruned from receive queue because of socket buffer overrun
?
相关推荐
- 0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)
-
文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...
- ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes
-
为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...
- 生产环境starrocks 3.1存算一体集群部署
-
集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...
- 在CentOS上添加swap虚拟内存并设置优先级
-
现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...
- 国产深度(deepin)操作系统优化指南
-
1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...
- postgresql-15.4 多节点主从(读写分离)
-
1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...
- Docker 容器 Java 服务内存与 GC 优化实施方案
-
一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...
- 虚拟内存设置、解决linux内存不够问题
-
虚拟内存设置(解决linux内存不够情况)背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...
- Elasticsearch性能调优(5):服务器配置选择
-
在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...
- Es如何落地
-
一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...
- 针对Linux内存管理知识学习总结
-
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...
- MySQL进阶之性能优化
-
概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...
- Linux Cgroups(Control Groups)原理
-
LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...
- linux 常用性能优化参数及理解
-
1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...
- 如何在 Linux 中使用 Sysctl 命令?
-
sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)