上海网站制作网站建设,vps如何放置网站,上传网站中ftp地址写什么,东四网站建设热门IT课程【视频教程】-华为/思科/红帽/oraclehttps://xmws-it.blog.csdn.net/article/details/134398330 所谓丢包#xff0c;是指在网络数据的收发过程中#xff0c;由于种种原因#xff0c;数据包还没传输到应用程序中#xff0c;就被丢弃了。这些被丢弃包的数量#…热门IT课程【视频教程】-华为/思科/红帽/oraclehttps://xmws-it.blog.csdn.net/article/details/134398330 所谓丢包是指在网络数据的收发过程中由于种种原因数据包还没传输到应用程序中就被丢弃了。这些被丢弃包的数量除以总的传输包数也就是我们常说的丢包率。丢包率是网络性能中最核心的指标之一。丢包通常会带来严重的性能下降特别是对 TCP 来说丢包通常意味着网络拥塞和重传进而还会导致网络延迟增大、吞吐降低。 一、 哪里可能丢包
接下来我就以最常用的反向代理服务器 Nginx 为例带你一起看看如何分析网络丢包的问题。执行下面的 hping3 命令进一步验证 Nginx 是不是可以正常访问。这里我没有使用 ping是因为 ping 基于 ICMP 协议而 Nginx 使用的是 TCP 协议。
# -c表示发送10个请求-S表示使用TCP SYN-p指定端口为80
hping3 -c 10 -S -p 80 192.168.0.30HPING 192.168.0.30 (eth0 192.168.0.30): S set, 40 headers 0 data bytes
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq3 win5120 rtt7.5 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq4 win5120 rtt7.4 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq5 win5120 rtt3.3 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq7 win5120 rtt3.0 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq6 win5120 rtt3027.2 ms--- 192.168.0.30 hping statistic ---
10 packets transmitted, 5 packets received, 50% packet loss
round-trip min/avg/max 3.0/609.7/3027.2 ms从 hping3 的输出中我们可以发现发送了 10 个请求包却只收到了 5 个回复50%的包都丢了。再观察每个请求的 RTT 可以发现RTT 也有非常大的波动变化小的时候只有 3ms而大的时候则有 3s。根据这些输出我们基本能判断已经发生了丢包现象。可以猜测3s 的 RTT 很可能是因为丢包后重传导致的。
那到底是哪里发生了丢包呢排查之前我们可以回忆一下 Linux 的网络收发流程先从理论上分析哪里有可能会发生丢包。你不妨拿出手边的笔和纸边回忆边在纸上梳理思考清楚再继续下面的内容。在这里为了帮你理解网络丢包的原理我画了一张图你可以保存并打印出来使用
从图中你可以看出可能发生丢包的位置实际上贯穿了整个网络协议栈。换句话说全程都有丢包的可能。 在两台 VM 连接之间可能会发生传输失败的错误比如网络拥塞、线路错误等 在网卡收包后环形缓冲区可能会因为溢出而丢包 在链路层可能会因为网络帧校验失败、QoS 等而丢包 在 IP 层可能会因为路由失败、组包大小超过 MTU 等而丢包 在传输层可能会因为端口未监听、资源占用超过内核限制等而丢包 在套接字层可能会因为套接字缓冲区溢出而丢包 在应用层可能会因为应用程序异常而丢包 此外如果配置了 iptables 规则这些网络包也可能因为 iptables过滤规则而丢包 当然上面这些问题还有可能同时发生在通信的两台机器中。不过由于我们没对 VM2做任何修改并且 VM2 也只运行了一个最简单的 hping3 命令这儿不妨假设它是没有问题的。为了简化整个排查过程我们还可以进一步假设 VM1 的网络和内核配置也没问题。接下来就可以从协议栈中逐层排查丢包问题。 二、 链路层
当链路层由于缓冲区溢出等原因导致网卡丢包时Linux 会在网卡收发数据的统计信息中记录下收发错误的次数。可以通过 ethtool 或者 netstat 来查看网卡的丢包记录。
netstat -iKernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 100 31 0 0 0 8 0 0 0 BMRU
lo 65536 0 0 0 0 0 0 0 0 LRURX-OK、RX-ERR、RX-DRP、RX-OVR 分别表示接收时的总包数、总错误数、进入 Ring Buffer 后因其他原因如内存不足导致的丢包数以及 Ring Buffer 溢出导致的丢包数。
TX-OK、TX-ERR、TX-DRP、TX-OVR 也代表类似的含义只不过是指发送时对应的各个指标。
这里我们没有发现任何错误说明虚拟网卡没有丢包。不过要注意如果用 tc 等工具配置了 QoS那么 tc 规则导致的丢包就不会包含在网卡的统计信息中。所以接下来我们还要检查一下 eth0 上是否配置了 tc 规则并查看有没有丢包。添加 -s 选项以输出统计信息
tc -s qdisc show dev eth0qdisc netem 800d: root refcnt 2 limit 1000 loss 30%Sent 432 bytes 8 pkt (dropped 4, overlimits 0 requeues 0)backlog 0b 0p requeues 0可以看到 eth0 上配置了一个网络模拟排队规则qdisc netem并且配置了丢包率为 30%loss 30%。再看后面的统计信息发送了 8 个包但是丢了 4个。看来应该就是这里导致 Nginx 回复的响应包被 netem 模块给丢了。
既然发现了问题解决方法也很简单直接删掉 netem 模块就可以了。执行下面的命令删除 tc 中的 netem 模块
tc qdisc del dev eth0 root netem loss 30%删除后重新执行之前的 hping3 命令看看现在还有没有问题
hping3 -c 10 -S -p 80 192.168.0.30HPING 192.168.0.30 (eth0 192.168.0.30): S set, 40 headers 0 data bytes
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq0 win5120 rtt7.9 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq2 win5120 rtt1003.8 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq5 win5120 rtt7.6 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq6 win5120 rtt7.4 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq9 win5120 rtt3.0 ms--- 192.168.0.30 hping statistic ---
10 packets transmitted, 5 packets received, 50% packet loss
round-trip min/avg/max 3.0/205.9/1003.8 ms不幸的是从 hping3 的输出中可以看到还是 50% 的丢包RTT 的波动也仍旧很大从 3ms 到 1s。显然问题还是没解决丢包还在继续发生。不过既然链路层已经排查完了我们就继续向上层分析看看网络层和传输层有没有问题。 三、 网络层和传输层
在网络层和传输层中引发丢包的因素非常多。不过其实想确认是否丢包是非常简单的事因为 Linux 已经为我们提供了各个协议的收发汇总情况。执行 netstat -s 命令可以看到协议的收发汇总以及错误信息
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 predictedTCPTimeouts: 7 //超时数TCPSynRetrans: 4 //SYN重传数...etstat 汇总了 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 协议有多次超时和失败重试并且主要错误是半连接重置。换句话说主要的失败都是三次握手失败。不过虽然在这儿看到了这么多失败但具体失败的根源还是无法确定。所以我们还需要继续顺着协议栈来分析。接下来的几层又该如何分析呢 四、 iptables
首先除了网络层和传输层的各种协议iptables 和内核的连接跟踪机制也可能会导致丢包。所以这也是发生丢包问题时我们必须要排查的一个因素。
先来看看连接跟踪要确认是不是连接跟踪导致的问题只需要对比当前的连接跟踪数和最大连接跟踪数即可。
# 主机终端中查询内核配置
$ sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max 262144
$ sysctl net.netfilter.nf_conntrack_count
net.netfilter.nf_conntrack_count 182可以看到连接跟踪数只有 182而最大连接跟踪数则是 262144。显然这里的丢包不可能是连接跟踪导致的。
接着再来看 iptables。回顾一下 iptables 的原理它基于 Netfilter 框架通过一系列的规则对网络数据包进行过滤如防火墙和修改如 NAT。这些 iptables 规则统一管理在一系列的表中包括 filter、nat、mangle用于修改分组数据 和 raw用于原始数据包等。而每张表又可以包括一系列的链用于对 iptables 规则进行分组管理。
对于丢包问题来说最大的可能就是被 filter 表中的规则给丢弃了。要弄清楚这一点就需要我们确认那些目标为 DROP 和 REJECT 等会弃包的规则有没有被执行到。可以直接查询 DROP 和 REJECT 等规则的统计信息看看是否为0。如果不是 0 再把相关的规则拎出来进行分析。
iptables -t filter -nvL
#输出
Chain INPUT (policy ACCEPT 25 packets, 1000 bytes)pkts bytes target prot opt in out source destination6 240 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.29999999981Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)pkts bytes target prot opt in out source destinationChain OUTPUT (policy ACCEPT 15 packets, 660 bytes)pkts bytes target prot opt in out source destination6 264 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 statistic mode random probability 0.29999999981从 iptables 的输出中你可以看到两条 DROP 规则的统计数值不是 0它们分别在INPUT 和 OUTPUT 链中。这两条规则实际上是一样的指的是使用 statistic 模块进行随机 30% 的丢包。0.0.0.0/0 表示匹配所有的源 IP 和目的 IP也就是会对所有包都进行随机 30% 的丢包。看起来这应该就是导致部分丢包的“罪魁祸首”了。
执行下面的两条 iptables 命令删除这两条 DROP 规则。
rootnginx:/# iptables -t filter -D INPUT -m statistic --mode random --probability 0.30 -j DROP
rootnginx:/# iptables -t filter -D OUTPUT -m statistic --mode random --probability 0.30 -j DROP再次执行刚才的 hping3 命令看看现在是否正常
hping3 -c 10 -S -p 80 192.168.0.30
#输出
HPING 192.168.0.30 (eth0 192.168.0.30): S set, 40 headers 0 data bytes
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq0 win5120 rtt11.9 ms
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq1 win5120 rtt7.8 ms
...
len44 ip192.168.0.30 ttl63 DF id0 sport80 flagsSA seq9 win5120 rtt15.0 ms--- 192.168.0.30 hping statistic ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max 3.3/7.9/15.0 ms这次输出你可以看到现在已经没有丢包了并且延迟的波动变化也很小。看来丢包问题应该已经解决了。
不过到目前为止我们一直使用的 hping3 工具只能验证案例 Nginx 的 80 端口处于正常监听状态却还没有访问 Nginx 的 HTTP 服务。所以不要匆忙下结论结束这次优化我们还需要进一步确认Nginx 能不能正常响应 HTTP 请求。我们继续在终端二中执行如下的 curl 命令检查 Nginx 对 HTTP 请求的响应
$ curl --max-time 3 http://192.168.0.30
curl: (28) Operation timed out after 3000 milliseconds with 0 bytes received奇怪hping3 的结果显示Nginx 的 80 端口是正常状态为什么还是不能正常响应 HTTP 请求呢别忘了我们还有个大杀器——抓包操作。看来有必要抓包看看了。 五、 tcpdump
执行下面的 tcpdump 命令抓取 80 端口的包
tcpdump -i eth0 -nn port 80
#输出
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes然后切换到终端二中再次执行前面的 curl 命令
curl --max-time 3 http://192.168.0.30
curl: (28) Operation timed out after 3000 milliseconds with 0 bytes received等到 curl 命令结束后再次切换回终端一查看 tcpdump 的输出
14:40:00.589235 IP 10.255.255.5.39058 172.17.0.2.80: Flags [S], seq 332257715, win 29200, options [mss 1418,sackOK,TS val 486800541 ecr 0,nop,wscale 7], length 0
14:40:00.589277 IP 172.17.0.2.80 10.255.255.5.39058: Flags [S.], seq 1630206251, ack 332257716, win 4880, options [mss 256,sackOK,TS val 2509376001 ecr 486800541,nop,wscale 7], length 0
14:40:00.589894 IP 10.255.255.5.39058 172.17.0.2.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 486800541 ecr 2509376001], length 0
14:40:03.589352 IP 10.255.255.5.39058 172.17.0.2.80: Flags [F.], seq 76, ack 1, win 229, options [nop,nop,TS val 486803541 ecr 2509376001], length 0
14:40:03.589417 IP 172.17.0.2.80 10.255.255.5.39058: Flags [.], ack 1, win 40, options [nop,nop,TS val 2509379001 ecr 486800541,nop,nop,sack 1 {76:77}], length 0从 tcpdump 的输出中我们就可以看到 前三个包是正常的 TCP 三次握手这没问题 但第四个包却是在 3 秒以后了并且还是客户端VM2发送过来的 FIN 包说明客户端的连接关闭了
根据 curl 设置的 3 秒超时选项你应该能猜到这是因为 curl 命令超时后退出了。用 Wireshark 的 Flow Graph 来表示
你可以更清楚地看到上面这个问题 这里比较奇怪的是我们并没有抓取到 curl 发来的 HTTP GET 请求。那究竟是网卡丢包了还是客户端就没发过来呢
可以重新执行 netstat -i 命令确认一下网卡有没有丢包问题
netstat -iKernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 100 157 0 344 0 94 0 0 0 BMRU
lo 65536 0 0 0 0 0 0 0 0 LRU从 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修改完成后再切换到终端二中再次执行 curl 命令确认问题是否真的解决了
curl --max-time 3 http://192.168.0.30/
#输出
!DOCTYPE html
html
...
pemThank you for using nginx./em/p
/body
/html非常不容易呀这次终于看到了熟悉的 Nginx 响应说明丢包的问题终于彻底解决了。
1