用了TCP协议就一定不会丢包吗( 二 )


半连接队列和全连接队列
是队列就有长度,有长度就有可能会满,如果它们满了,那新来的包就会被丢弃 。
可以通过下面的方式查看是否存在这种丢包行为 。
# 全连接队列溢出次数# netstat -s | grep overflowed4343 times the listen queue of a socket overflowed# 半连接队列溢出次数# netstat -s | grep -i "SYNs to LISTEN sockets dropped"109 times the listen queue of a socket overflowed
从现象来看就是连接建立失败 。
这个话题在之前写的《没有,能建立TCP连接吗?》有更详细的聊过,感兴趣的可以回去看下 。
流量控制丢包
应用层能发网络数据包的软件有那么多,如果所有数据不加控制一股脑冲入到网卡,网卡会吃不消,那怎么办?让数据按一定的规则排个队依次处理,也就是所谓的qdisc(,排队规则),这也是我们常说的流量控制机制 。
排队,得先有个队列,而队列有个长度 。
我们可以通过下面的命令查看到,里面涉及到的后面的数字1000,其实就是流控队列的长度 。
当发送数据过快,流控队列长度又不够大时,就容易出现丢包现象 。
qdisc丢包
可以通过下面的命令,查看TX下的字段,当它大于0时,则有可能是发生了流控丢包 。
# ifconfig eth0eth0: flags=4163mtu 1500inet 172.21.66.69netmask 255.255.240.0broadcast 172.21.79.255inet6 fe80::216:3eff:fe25:269fprefixlen 64scopeid 0x20ether 00:16:3e:25:26:9ftxqueuelen 1000(Ethernet)RX packets 6962682bytes 1119047079 (1.0 GiB)RX errors 0dropped 0overruns 0frame 0TX packets 9688919bytes 2072511384 (1.9 GiB)TX errors 0dropped 0 overruns 0carrier 0collisions 0

用了TCP协议就一定不会丢包吗

文章插图
当遇到这种情况时,我们可以尝试修改下流控队列的长度 。比如像下面这样将eth0网卡的流控队列长度从1000提升为1500.
# ifconfig eth0 txqueuelen 1500
网卡丢包
网卡和它的驱动导致丢包的场景也比较常见,原因很多,比如网线质量差,接触不良 。除此之外,我们来聊几个常见的场景 。
过小导致丢包
上面提到,在接收数据时,会将数据暂存到接收缓冲区中,然后等着内核触发软中断慢慢收走 。如果这个缓冲区过小,而这时候发送的数据又过快,就有可能发生溢出,此时也会产生丢包 。
满了导致丢包
我们可以通过下面的命令去查看是否发生过这样的事情 。
# ifconfigeth0:RX errors 0dropped 0overruns 0frame 0
查看上面的指标,它记录了由于长度不足导致的溢出次数 。
当然,用命令也能查看 。
# ethtool -S eth0|grep rx_queue_0_drops
但这里需要注意的是,因为一个网卡里是可以有多个的,所以上面的里的0代表的是第0个的丢包数,对于多队列的网卡,这个0还可以改成其他数字 。但我的家庭条件不允许我看其他队列的丢包数,所以上面的命令对我来说是够用了 。。。
当发现有这类型丢包的时候,可以通过下面的命令查看当前网卡的配置 。
#ethtool -g eth0Ring parameters for eth0:Pre-set maximums:RX:4096RX Mini:0RX Jumbo:0TX:4096Current hardware settings:RX:1024RX Mini:0RX Jumbo:0TX:1024
上面的输出内容,含义是最大支持4096的长度,但现在实际只用了1024 。
想要修改这个长度可以执行 -G eth1 rx 4096 tx 4096将发送和接收的长度都改为4096 。
【用了TCP协议就一定不会丢包吗】