查看: 1414|回复: 0

TCP传输效率翻倍的秘密武器:SACK如何拯救你的网络性能?

[复制链接]
发表于 2025-2-24 17:04:01 | 显示全部楼层 |阅读模式
本文是《从时序图看TCP》系列的第十篇,上一篇内容 《性能优化重要知识点:TCP滑动窗口、WSOPT的分析技巧》 我们深入探讨了WSOPT的分析、TCP零窗口、坚持计时器等窗口问题在CSNAS时序图中的分析方法,本文将继续围绕时序图和大家介绍TCP的SACK选项的相关知识。

凌晨3点,某电商平台突发流量高峰,服务器频繁丢包导致支付失败。运维团队排查发现,问题竟源于一个被忽视的TCP选项——SACK。这个看似微小的配置,如何成为压垮系统的最后一根稻草?

  丢包后,是否会产生不必要的重传?

先提出一个问题,假设网络中发生了如下情况:

  • 当TCP发送方计划发送①-⑥这六个数据包,目前已经连续发送了①②③④⑤号数据包
  • 发送方的③在传输过程中丢包
  • 接收方只收到①②④⑤
  • 发送方发现③丢包并重传③

那么,接下来,发送方应该继续发送④,还是继续发送⑥?

由于TCP累积确认的机制存在,接收方可以在收到③的重传后,通过确认③或确认⑤来声明自己接收到哪些数据包。本文讨论的情况,是发送方暂未接收到针对③的ACK包时的情况,如下图所示:

图1

在发送方未接收到针对③的ACK时,继续发送④或继续发送⑥都是盲目且不合适的。问题的关键在于,发送方是否能够获知④和⑤是否已经被接收方收到?

针对上述情况,如果有一种机制,能够让接收方只收到①②④⑤的情况下,先对②进行累积确认,同时声明④和⑤已经正确收到的情况,那么发送方就可以正确决定该继续发④或⑥了。

由于每个TCP数据包只有一个ACK字段,并且ACK字段默认是累积确认的,这就导致接收方无法在未收到③的时候去确认④和⑤。

  什么是SACK选项?

SACK(Selective Acknowledgment)选项的出现正是为了弥补这一问题,其通过TCP选项的方式传输,实现允许接收方对非连续的TCP段进行单独确认,使发送方只重传丢失的片段。SACK选项能够在乱序和丢包的情况下提高TCP传输的效率。

结合前文的例子来说,SACK允许接收方使用TCP ACK字段确认②,并通过TCP SACK选项确认④和⑤。

  如何分析SACK选项?

SACK是如何实现该功能的?首先,该功能需要通信双方支持。在连接建立的SYN包和SYN/ACK包中,需要双方声明自己支持SACK,会话才会启用SACK功能。

在启用了SACK功能的会话中,如果出现了丢包,那么一般会触发重复ACK。在重复ACK包中,接收方会使用另一种TCP选项声明已经接收到的“④和⑤”。

因此,SACK实际是两种选项,一种选项为SACK允许选项(Sack-Permitted),选项类型为04,用于声明自己支持SACK功能,如果双方都支持SACK,那么在后续的连接通信过程中就可以使用SACK选项;另一种选项为SACK本身,选项类型为05,用于进行“选择性确认”。

选项04的SACK允许,在实际流量分析中,如下图所示:

图2

图3

选项05的SACK,一般出现在重复ACK中,如下图所示:

图4

通过图2、3可以看出,“SACK允许”选项的格式相对简单,选项类型为04,选项长度为02字节,仅用于声明支持此功能。

通过图4可以看出,“SACK”选项的格式相对复杂,选项类型为05,长度为10字节,块左边界长度为4字节,块右边界长度为4字节。

块左边界和块右边界的概念,是前文中示例的④+⑤数据包的左边界和右边界。左边界为④的Seq,右边界为⑤的Seq+Len。由于④和⑤是连续的两个包,因此两个包被合并为同一个块。

把图1中的关键信息进行完善,得到下图:

图5

图中①-⑥数据包的长度均为100,起始Seq号为100,并模拟了发送方③丢包和接收方SACK的情况。

当接收方收到①②④⑤时,可以用ACK号300来表示接收到了Seq为300之前的数据,即①和②;同时使用SACK表示接收到了Seq为400-499,500-599这两个包的数据,即④和⑤;由于④和⑤是连续的数据,在SACK中可以合并为一个块。因此SACK块左边界为400,块右边界为600。

“SACK”选项包含了具体的SACK信息,它告诉对方已经接收哪些数据,发送方可以根据这些信息判断具体丢了哪些包。

  有了SACK后,发送方如何处理重传?

接下来看一个SACK在TCP会话中的实际应用过程:


图6

服务器发送了序号为429、430、431的三个数据包,其中430号数据包发生了丢包。

客户端通过432号包进行确认,Ack号为3589769219,仅对429号包进行了确认。同时客户端通过SACK的块左边界3589770679和块右边界3589772139声明已经收到了431号包。

随后服务器又连续发送了序号为433、434、435、436这4个数据包,客户端正常收到了这4个数据包,但由于累积确认的存在,客户端不能确认这4个数据包,只能利用437、438、439、440号数据包重复对432号数据包的确认。

客户端发送的4个数据包均携带SACK,观察客户端发送的440号,如下图所示:


图7

440号数据包携带SACK选项,块左边界为3589770679,块右边界为3589777979,结合服务器之前发送的数据包看,这正巧是服务器发送的431、433、434、435、436这五个连续的数据。


图8

过了约34ms,服务器又发送了441号、442号数据包,并通过443号数据包重传了丢失的430号数据包。随后,服务器通过444号数据包继续发送442号数据包后的数据。结合之前的示例,本例中的429即为①②数据包,430即为③,431、433、434、435、436、441、442即为④⑤数据包,444即为⑥。服务器在重传③后,继续发送了⑥,而非继续发送④,这全是SACK的作用。

通过SACK选项,接收方可以通知发送方哪些数据块已经收到,哪些数据块丢失,从而避免发送方重传已经成功接收的数据块,减少不必要的网络拥塞和提高传输效率。

  典型的故障实例  

放一张图,你能否从这张图中看出导致网络故障的端倪?


图9


本文介绍了TCP的SACK选项,深入探讨了SACK选项的作用、工作方法,以及在科来网络分析系统中的TCP时序图功能中的分析方法,通过深入SACK选项的分析技巧,能够提升流量分析工程师在工作中快速分析解决此类故障的能力。

思考题:

• 如果接收方SACK块缓冲区溢出,会发生什么?

• SACK能否完全替代快速重传(Fast Retransmit)?
欢迎在评论区或公众号后台和我们讨论交流~

免费易用的流量分析工具下载
扫码关注公众号
更多网络分析技术、技巧、干货分享


- End -


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?CSNA会员注册

×
回复

使用道具 举报

您需要登录后才可以回帖 登录 | CSNA会员注册

本版积分规则

快速回复 返回顶部 返回列表