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

简介: 用了TCP协议,就一定不会丢包吗?

表面上我是个技术博主

但没想到今天成了个情感博主

我是没想到有一天,我会通过技术知识,来挽救粉丝即将破碎的感情。

掏心窝子的说。这件事情多少是沾点功德无量了。

事情是这样的。

最近就有个读者加了我的绿皮聊天软件,女生,头像挺好看的,就在我以为她要我拉她进群发成人专升本广告的时候。

画风突然不对劲。

她说她男朋友也是个程序员,异地恋,也关注了我,天天研究什么TCP,UDP网络。一研究就是一晚上,一晚上都不回她消息的那种。

话里有话,懂。

不出意外的出了意外,她发出了灵魂拷问

"你们程序员真的有那么忙吗?忙到连消息都不知道回。"

没想到上来就是一记直拳。

但是,这一拳,我接住了。


我很想告诉她"分了吧,下一题"。

但我不能。因为这样我就伤害了我的读者兄弟。

沉默了一下。


单核cpu都快转冒烟了,才颤颤巍巍在九宫格键盘上发出消息。

再回慢一点,我就感觉,我要对不起我这全日制本科学历了。

"其实,他已经回了你消息了,但你知道吗?网络是会丢包的。"

"我来帮他解释下,这个话题就要从数据包的发送流程聊起"


数据包的发送流程

首先,我们两个手机的绿皮聊天软件客户端,要通信,中间会通过它们家服务器。大概长这样。

聊天软件三端通信

但为了简化模型,我们把中间的服务器给省略掉,假设这是个端到端的通信。且为了保证消息的可靠性,我们盲猜它们之间用的是TCP协议进行通信。

聊天软件两端通信


为了发送数据包,两端首先会通过三次握手,建立TCP连接。

一个数据包,从聊天框里发出,消息会从聊天软件所在的用户空间拷贝到内核空间发送缓冲区(send buffer),数据包就这样顺着传输层、网络层,进入到数据链路层,在这里数据包会经过流控(qdisc),再通过RingBuffer发到物理层的网卡。数据就这样顺着网卡发到了纷繁复杂的网络世界里。这里头数据会经过n多个路由器和交换机之间的跳转,最后到达目的机器的网卡处。

此时目的机器的网卡会通知DMA将数据包信息放到RingBuffer中,再触发一个硬中断CPUCPU触发软中断ksoftirqdRingBuffer收包,于是一个数据包就这样顺着物理层,数据链路层,网络层,传输层,最后从内核空间拷贝到用户空间里的聊天软件里。

网络发包收包全景图

画了那么大一张图,只水了200字做解释,我多少是有些心痛的。


到这里,抛开一些细节,大家大概知道了一个数据包从发送到接收的宏观过程。


可以看到,这上面全是密密麻麻的名词

整条链路下来,有不少地方可能会发生丢包。

但为了不让大家保持蹲姿太久影响身体健康,我这边只重点讲下几个常见容易发生丢包的场景


建立连接时丢包

TCP协议会通过三次握手建立连接。大概长下面这样。

TCP三次握手

在服务端,第一次握手之后,会先建立个半连接,然后再发出第二次握手。这时候需要有个地方可以暂存这些半连接。这个地方就叫半连接队列

如果之后第三次握手来了,半连接就会升级为全连接,然后暂存到另外一个叫全连接队列的地方,坐等程序执行accept()方法将其取走使用。

半连接队列和全连接队列

是队列就有长度,有长度就有可能会满,如果它们满了,那新来的包就会被丢弃

可以通过下面的方式查看是否存在这种丢包行为。

# 全连接队列溢出次数
# netstat -s | grep overflowed
    4343 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

从现象来看就是连接建立失败。


这个话题在之前写的《没有accept,能建立TCP连接吗?》有更详细的聊过,感兴趣的可以回去看下。


流量控制丢包

应用层能发网络数据包的软件有那么多,如果所有数据不加控制一股脑冲入到网卡,网卡会吃不消,那怎么办?让数据按一定的规则排个队依次处理,也就是所谓的qdisc(Queueing Disciplines,排队规则),这也是我们常说的流量控制机制。

排队,得先有个队列,而队列有个长度

我们可以通过下面的ifconfig命令查看到,里面涉及到的txqueuelen后面的数字1000,其实就是流控队列的长度。

当发送数据过快,流控队列长度txqueuelen又不够大时,就容易出现丢包现象。

qdisc丢包

可以通过下面的ifconfig命令,查看TX下的dropped字段,当它大于0时,则有可能是发生了流控丢包。

# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.21.66.69  netmask 255.255.240.0  broadcast 172.21.79.255
        inet6 fe80::216:3eff:fe25:269f  prefixlen 64  scopeid 0x20<link>
        ether 00:16:3e:25:26:9f  txqueuelen 1000  (Ethernet)
        RX packets 6962682  bytes 1119047079 (1.0 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 9688919  bytes 2072511384 (1.9 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

当遇到这种情况时,我们可以尝试修改下流控队列的长度。比如像下面这样将eth0网卡的流控队列长度从1000提升为1500.

# ifconfig eth0 txqueuelen 1500


网卡丢包

网卡和它的驱动导致丢包的场景也比较常见,原因很多,比如网线质量差,接触不良。除此之外,我们来聊几个常见的场景。


RingBuffer过小导致丢包

上面提到,在接收数据时,会将数据暂存到RingBuffer接收缓冲区中,然后等着内核触发软中断慢慢收走。如果这个缓冲区过小,而这时候发送的数据又过快,就有可能发生溢出,此时也会产生丢包

RingBuffer满了导致丢包

我们可以通过下面的命令去查看是否发生过这样的事情。

# ifconfig
eth0:  RX errors 0  dropped 0  overruns 0  frame 0

查看上面的overruns指标,它记录了由于RingBuffer长度不足导致的溢出次数。


当然,用ethtool命令也能查看。

# ethtool -S eth0|grep rx_queue_0_drops

但这里需要注意的是,因为一个网卡里是可以有多个RingBuffer的,所以上面的rx_queue_0_drops里的0代表的是第0个RingBuffer的丢包数,对于多队列的网卡,这个0还可以改成其他数字。但我的家庭条件不允许我看其他队列的丢包数,所以上面的命令对我来说是够用了。。。

当发现有这类型丢包的时候,可以通过下面的命令查看当前网卡的配置。

#ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:        4096
RX Mini:    0
RX Jumbo:    0
TX:        4096
Current hardware settings:
RX:        1024
RX Mini:    0
RX Jumbo:    0
TX:        1024

上面的输出内容,含义是RingBuffer最大支持4096的长度,但现在实际只用了1024。

想要修改这个长度可以执行ethtool -G eth1 rx 4096 tx 4096将发送和接收RingBuffer的长度都改为4096。

RingBuffer增大之后,可以减少因为容量小而导致的丢包情况。


网卡性能不足

网卡作为硬件,传输速度是有上限的。当网络传输速度过大,达到网卡上限时,就会发生丢包。这种情况一般常见于压测场景。

我们可以通过ethtool加网卡名,获得当前网卡支持的最大速度。

# ethtool eth0
Settings for eth0:
    Speed: 10000Mb/s

可以看到,我这边用的网卡能支持的最大传输速度speed=1000Mb/s

也就是俗称的千兆网卡,但注意这里的单位是Mb,这里的b是指bit,而不是Byte。1Byte=8bit。所以10000Mb/s还要除以8,也就是理论上网卡最大传输速度是1000/8 = 125MB/s

我们可以通过sar命令从网络接口层面来分析数据包的收发情况。

# sar -n DEV 1
Linux 3.10.0-1127.19.1.el7.x86_64      2022年07月27日     _x86_64_    (1 CPU)
08时35分39秒     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s    rxcmp/s   txcmp/s  rxmcst/s
08时35分40秒      eth0      6.06      4.04      0.35    121682.33   0.00    0.00     0.00

其中 txkB/s是指当前每秒发送的字节(byte)总数,rxkB/s是指每秒接收的字节(byte)总数

当两者加起来的值约等于12~13w字节的时候,也就对应大概125MB/s的传输速度。此时达到网卡性能极限,就会开始丢包。

遇到这个问题,优先看下你的服务是不是真有这么大的真实流量,如果是的话可以考虑下拆分服务,或者就忍痛充钱升级下配置吧。

目录
相关文章
|
iOS开发 开发者
iOS 上架报错:无法添加以供审核
iOS 上架报错:无法添加以供审核
|
机器学习/深度学习 网络协议 Java
聊聊 wireshark 的重传包和重复包(Duplicate Packets or TCP Retransmissions?)
聊聊 wireshark 的重传包和重复包(Duplicate Packets or TCP Retransmissions?)
|
8月前
|
网络协议 算法 安全
TCP协议(三次握手、流量控制、拥塞控制)
TCP协议是一种可靠的传输层通信协议,通过三次握手建立连接,确保数据安全传输。流量控制通过接收窗口避免接收方缓冲区溢出,拥塞控制则利用拥塞窗口调节网络传输速度,防止网络拥堵。三者协同工作,保障TCP在复杂网络环境中实现高效、可靠的数据传输。
2647 11
|
机器学习/深度学习 人工智能 算法
「AI工程师」算法研发与优化-工作指导
**工作指导书摘要:** 设计与优化算法,提升性能效率;负责模型训练及测试,确保准确稳定;跟踪业界最新技术并应用;提供内部技术支持,解决使用问题。要求扎实的数学和机器学习基础,熟悉深度学习框架,具备良好编程及数据分析能力,注重团队协作。遵循代码、文档和测试规范,持续学习创新,优化算法以支持业务发展。
683 0
「AI工程师」算法研发与优化-工作指导
|
缓存 人工智能 运维
昇腾集群PFC现象分析
负责集群运维的同学可能都遇到过PFC现象,那么PFC到底是啥?产生原因是什么?这篇文章提供了一些分析。
264 1
|
存储 SQL 数据库
Sql Server 存储过程怎么找 存储过程内容
Sql Server 存储过程怎么找 存储过程内容
756 1
|
机器学习/深度学习 编解码 人工智能
Vision Mamba:将Mamba应用于计算机视觉任务的新模型
Mamba是LLM的一种新架构,与Transformers等传统模型相比,它能够更有效地处理长序列。就像VIT一样现在已经有人将他应用到了计算机视觉领域,让我们来看看最近的这篇论文“Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Models,”
1348 7
|
JavaScript 前端开发 开发工具
Flutter&鸿蒙next 中如何实现 WebView【跳、显、适、反】等一些基础问题
在 Flutter 项目中集成 WebView 可以展示网页或进行在线操作。本文介绍了如何添加依赖、配置平台权限、创建 WebView 页面、适配不同机型、处理页面间参数传递等详细步骤,帮助开发者高效实现 WebView 功能,提升用户体验。
768 4
|
网络协议 网络架构
什么是TCP重传?
【4月更文挑战第12天】
1506 3
|
Linux 数据库 iOS开发
超级签名源码/超级签/ios分发/签名端本地linux服务器完成签名
该系统完全在linux下运行,不存在使用第三方收费工具,市面上很多系统都是使用的是第三方收费系统,例如:某心签名工具,某测侠等,不开源而且需要每年交费,这种系统只是在这些工具的基础上套了一层壳。请需要系统的放大你们的眼睛。
270 0