弱网环境是丢包率较高的特殊场景,TCP 在类似场景中的表现很差,当 RTT 为 30ms 时,一旦丢包率达到了 2%,TCP 的吞吐量就会下降 89.9%[3],从下面的表中我们可以看出丢包对 TCP 的吞吐量极其显著的影响:

tcp/ip 拥塞控制、重传、丢包、优化-风君雪科技博客

概念理解

4种计时器

1.重传计时器:Retransmission Timer A发报文时创建计时器,计时器到期内收到回报文ACK,就撤销计时器

2.持久计时器:Persistent Timer B告诉A,接收窗口填满了(0窗口通报),告诉A停止发送,进入等待,直到B发送报文告诉A已有“非零窗口”,但此时若这个报文丢失,B自己不知道,等着A发数据过来,双方都进入等待死锁,解决这个问题要在A端创建持久计时器,当收到B发送过来的0窗口通报报文后,计时器启动,计时器过期后,A发一个探测报文给B,询问是否有非0窗口,如果超时还没ack恢复则发探查报文,如果超时前收到到ack回复依然是0窗口,则将计时器复位并且翻倍时间值(1,2,4,8最大60s),如此循环,直到收到B的重开窗口确认包。

3.保活计时器:Keeplive Timer 长连接中A发送数据给B,发送几个数据包之后,A出故障了,B等待2小时后发10个探测报文段(每个75分钟发一次),如果没有响应就终止连接

4.时间等待计时器:Timer_Wait Timer time_wati状态下发出的给被关闭端ack报文后等待时间(30~120s),一般设置一个msl(最长报文寿命)是60s

包重传的原因

tcp可靠性通过序列号和ack确认包保障,当tcp发送包之后,将这个包的副本数据段放到重传队列上启动重传计时器
1、如果对方反馈ack,则销毁数据段和计时器
2、如果对方没有反馈ack,则在计时器到期后发起重传

快速重传:A向B发送4个tcp报文段(n1,n2,n3,n4),B只收到(n1,n2,n4),其中n3丢失(也许只是延时到达),B发现失序立即生成 重复ACK包(重复确认n3),且发送三次给A,A重传该数据包

超时重传:定时器超时之后,重传包,计时器的时间为“大于平均往返延迟”

伪超时和重传:过早的判断了超时时间,导致发送方触发重传,RTT(连接往返时间)增长 超过RTO(重传超时时间)

包失序:ip层的包没有按顺序传输,严重失序时,接收方误以为包丢失,通知发送端重传,需要设置合理的重传阀值解决

包重复:重传包含一个数据包,以及两个副本,多次重复会导致B收到过多重复包,从而B生成重复的ack,容易触发伪快速重传,使用sack避免

sack:当出现包失序、网络丢包导致的接收方数据序队列出现空洞,sack选项可以提供确认信息(描述乱序、空洞),帮助A方有效的重传。

拥塞控制

作用1:防止A向B发送过多数据,导致B无法处理
作用2:防止tcp任意连接的一方向网络发送大量数据,导致网络拥塞崩溃

拥塞窗口大小(cwnd),双方的接收窗口大小(rwnd)

tcp三次握手中双方通过ack交换接收窗口大小,rwnd有带宽延迟乘积决定
客户端能同时传输的最大数据段的数量值就是 cwnd和接收方rwnd的最小值min(cwnd,rwnd),在linux中为tcp_init_cwnd10,就是10个
tcp传输中A的拥塞窗口大小根据B的响应进行调整
1、线性增长:经过一个RTT,拥塞窗口大小会加一(是不是慢启动)
2、积式减少:发送方发送的数据丢包的时候,拥塞控制 阀值会减半

例如默认linux,A同时能发10个数据段,我们网络是10M,RTT是40ms,每个数据段1460字节,根据BDP(带宽延迟积)计算,双方窗口大小上限35
a>b 10段 0.5RTT
a<b 0.5RTT
a>b 10段+10 0.5RTT 经过一次rtt,窗口段数加倍
a<b 0.5RTT
a>b 20段+20 0.5RTT 经过二次rtt,窗口段数加倍
第三次开始(3.5RTT)窗口数稳定在上限35,需要140ms时间
三次握手就是1.5RTT

弱网环境下(丢包率高)导致 TCP 性能问题的三个重要原因:

TCP 的拥塞控制在发生丢包时会进行退让,减少能够发送的数据段数量,但是丢包并不一定意味着网络拥塞,更多的可能是网络状况较差;
TCP 的三次握手带来了额外开销,这些开销不只包括需要传输更多的数据,还增加了首次传输数据的网络延迟;
TCP 的重传机制在数据包丢失时可能会重新传输已经成功接收的数据段,造成带宽的浪费;

优化

QUIC 协议是能否保证丢包率较高时的传输性能 https://blog.csdn.net/m0_37621078/article/details/106506532
除了 SACK 和 TFO 之外还有哪些手段可以优化 TCP 的性能?

了解接收数据库包的流程

1、网卡收到数据包
2、将数据包从网卡硬件缓存转移到服务器内存中。
3、通知内核处理
4、经过icp/ip协议逐层处理
5、应用程序通过read()从socket buffer读取数据

网卡接收数据包转移到主机内存

1、驱动在内存创建一块缓冲区(sk_buffer)
2、驱动将这个缓冲区的地址、大小信息(即接收描述符)加入到rx_ring_buffer。缓冲区地址是DMA使用的物理地址
3、驱动通知网卡有个新描述符
4、网卡从rx_ring_buffer取出描述符,得知缓冲区地址和大小
5、网卡将数据包通过DMA直接写到sk_buffer
tcp/ip 拥塞控制、重传、丢包、优化-风君雪科技博客

网卡丢包原因1

驱动处理速度跟不上网卡接收包速度,驱动来不及分配缓冲区,网卡的数据无法实时写到sk_buffer,导致网卡内存缓冲区写满,开始丢弃部分数据,引起丢包。这部分丢包为rx_fifo_errors,在/proc/net/dev 中体现为filo 字段增长,在ifconfig 中体现为overruns指标增长。

网卡发起硬中断通知内核处理

硬中断:由硬件自己生产,具有随机性,硬中断被cpu接收后,触发执行中断处理程序,中断程力程序只会处理关键性、短时间内可完成的工作,剩余耗时交给软中断完成。(上半部分)

软中断:由硬中断对应的中断处理程序生成,一般是代码内实现好的,不具随机性。(下半部分)

数据被网卡通过DMA写到sk_buffer,网卡立即发起一个硬中断。cpu接收后,首先进入上半部分,cpu中断处理后,由网卡驱动程序发起软中断处理,进入下半部分,软中断处理程序开始消费sk_buffer 中的数据,交给内核协议栈处理。

通过中断,能够快速响应网卡数据请求,但是如果数量大,硬中断过多,导致cpu大量时间处理中断,效率降低。解决方案是内核、驱动采用NAP(new api)进行处理数据,即轮询+中断,数据量大时,一次硬中断后通过轮询接收一定数量数据包才后返回,减少硬中断导致的效率降低。

tcp/ip 拥塞控制、重传、丢包、优化-风君雪科技博客

ifconfig 下重点字段意思

RX errors 总的收包的错误数量,包含 too-long-frames 错误,Ring Buffer 溢出错误,crc 校验错误,帧同步错误,fifo overruns 以及 missed pkg 等等

RX dropped 表示数据包已经进入了网卡的接收缓存fifo队列 Ring Buffer,并且开始被系统中断处理准备进行数据包拷贝(从网卡缓存fifo队列拷贝到系统内存),但由于此时的系统原因(比如内存不够等)导致这个数据包被丢掉,即这个数据包被Linux系统丢掉。

RX overruns 表示了 fifo 的 overruns,这是由于 Ring Buffer(aka Driver Queue) 传输的 IO 大于 kernel 能够处理的 IO 导致的,而 Ring Buffer 则是指在发起 IRQ 中断请求之前的那块 buffer。表示这个数据包还没有被进入到网卡的接收缓存fifo队列就被丢掉,因此此时网卡的fifo是满的。为什么fifo会是满的?因为系统繁忙,来不及响应网卡中断,导致网卡里的数据包没有及时的拷贝到系统内存,fifo是满的就导致后面的数据包进不来,即这个数据包被网卡硬件丢掉。所以,个人觉得遇到overruns非0,需要检测cpu负载与cpu中断情况。很明显,overruns 的增大意味着数据包没到 Ring Buffer 就被网卡物理层给丢弃了,而 CPU 无法及时的处理中断是造成 Ring Buffer 满的原因之一,这样就会导致因为 interruprs 分布的不均匀 (都压在 core0),没有做 affinity 而造成的丢包。

RX frame 表示 misaligned 的 frames。

error是出现了网络错误,dropped是出现了格式不正确被丢弃的包,overruns 驱动缓冲不足或者网络中断处理不及时导致的缓冲溢出的数量

丢包排查思路

网卡工作在数据链路层,数据量链路层,会做一些校验,封装成帧。我们可以查看校验是否出错,确定传输是否存在问题。然后从软件层面,是否因为缓冲区太小丢包。

物理硬件方面

查看工作模式是否正常
ethtool eth0 | egrep ‘Speed|Duplex’

查看检验是否正常
ethtool -S eth0 | grep crc

软件层面overruns 和 buffer size

ethtool -g eth0
ethtool -G eth0 rx 2048
ethtool -G eth0 tx 2048

学习案例
http://blog.huoding.com/2020/04/27/814
https://blog.csdn.net/weixin_39630855/article/details/111265643?utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-2.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-2.nonecase