TCP 性能优化浅析

本文介绍TCP协议的关键原理,包括三次握手、流量控制和慢启动机制。同时探讨了TCP快速打开、窗口缩放及增大初始拥塞窗口等优化手段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

TCP 作为一种最常用的传输层协议,它的作用是在不可靠的传输信道上,提供可靠地数据传输。在各层网络协议中,只要有一层协议是可靠的,那么整个网络传输就是安全可靠的。现实中,几乎所有的 HTTP 流量都是经过 TCP 传输。因此,我们要进行 web 性能优化,TCP 是其中的关键一环。要针对 TCP 进行性能优化,就得理解其工作原理。

三次握手

众所周知,建立一次 TCP 连接需要进行三次握手。关于三次握手,一图胜千言。

三次握手给 TCP 带来了很大的延迟,不过这个握手过程是必不可少的。因为如果没有三次握手,有可能会出现一些已经失效的请求包突然又传到服务端,服务端认为这是客户端发起的一次新的连接,于是发出确认包,表示同意建立连接。而客户端并不会有响应,导致服务器出现空等,白白浪费服务器资源。

既然三次握手的过程不可避免,那么我们只能通过重用 TCP 连接,减少三次握手的次数。HTTP 1.1 引入了长连接,通过在请求头中加入 Connection: keep-alive, 来告诉请求响应完毕后,不要关闭连接。不过 HTTP 长连接也是有限制的,服务器通常会设置 keep-alive 超时时间和最大请求数,如果请求超时或者超过最大请求数,服务器会主动关闭连接。

除此之外,TFO(TCP Fast Open,TCP 快速打开)这种机制也被设计用于优化三次握手过程。它通过握手开始时的 SYN 包中的 TFO cookie(一个 TCP 选项)来验证一个之前连接过的客户端。如果验证成功,它可以在三次握手最终的 ACK 包收到之前就开始发送数据。

Linux 3.7 及以后的内核在客户端及服务器中支持 TFO, 对于移动端,Android 和 iOS 9+ 都支持 TFO,不过 iOS 并未默认启用。

PS: 推荐大家装一个 wireshark,可以非常直观的观察到三次握手的过程。

流量控制

流量控制是一种预防发送端向接受端发送过多数据的机制。它的主要目的是为了防止接收端服务过载,从而出现丢包。为了实现流量控制,TCP 连接的每一方都要声明自己的通告窗口(rwnd),表示自己的缓冲区最多能接收多少数据。如果其中一端跟不上对方的发送速度,就通知对方一个较小的窗口。如果窗口大小为 0,应用层必须先清空缓冲区,才能继续接收数据。这就是所谓的滑动窗口协议。

大家可能经常遇到这种情况,自己明明是百兆宽带,实际下载速度每秒却只有几M。这种情况有可能就是通告窗口(rwnd)设置的不合理造成的。最初的 TCP 规范分配给接收窗口大小的字段是 16 位,也就是 64KB(2 的 16 次方)。实际上,rwnd 的大小应该由 BDP(带宽延迟积) 而定。BDP(bit) = bandwidth(b/s) * round-trip time(s)。比如一个 100Mbps 的宽带,RTT 是100 ms,那么 BDP = (100 / 8) * 0.1 = 1.25M。此时,要想提高网络传输吞吐量,rwnd 应该为 1.25 M。

为了解决这个问题,TCP 窗口缩放(TCP Window Scaling)出现了,它将窗口大小由 16 位扩展到 32 位。Linux 上自带了缓冲大小调优机制,如下命令,可以查看 Linux 初始窗口大小:

sysctl net.ipv4.tcp_rmem
// 输出 net.ipv4.tcp_rmem = 4096	87380    6291456
// 从左到右一次为最小值、默认值、最大值
复制代码

慢启动

流量控制机制可以防止发送端和接收端之间的服务过载,但无法防止任何一端向某个网络的发送数据过载,因此还需要一个估算机制,根据网络环境动态改变数据传输速度,这就是慢启动出现的原因。

慢启动为发送方的 TCP 增加了一个窗口:拥塞窗口(congestion window),记为 cwnd。当与另一个网络的主机建立 TCP 连接时,cwnd 初始化为 1 个 TCP 段。每收到一个 ACK,cwnd 就增加一个 TCP 段。发送端取 cwnd 和 rwnd 中的最小值作为发送上限。可以这样理解,拥塞窗口是发送端使用的流量控制,而通告窗口是接收端使用的流量控制。

一开始 cwnd 为 1,发送方只发送一个 mss(最大报文段长度) 大小的数据包,收到 ack 后,cwnd 加 1,cwnd=2。

此时 cwnd 2,则发送方要发送两个 mss 大小的数据包,发送方会收到两个 ack,则 cwnd 会进行两次加一的操作,则也就是 cwnd+2,则 cwnd=4,也就是 cwnd = cwnd*2。

以此类推,每次 rtt 后,cwnd 都会变成上次发送前的 2 倍。因此,cwnd 的大小是呈指数级在递增。

随着 cwnd 的增加,会发送网络过载,此时会出现丢包。一旦发现有这种问题,cwnd 会成倍减少。

为了减少往返次数,初始拥塞窗口的大小设定就尤为重要。默认情况下(RFC 2581),初始 cwnd 为 4 个 MSS。Google 建议将初始窗口改为 10 个 MSS。根据 Google 的研究,90% 的 HTTP 请求数据都在 16KB 以内,约为 10 个 MSS。

总结

本文介绍了 TCP 的部分工作原理,包括三次握手、流量控制、慢启动,并阐述了 TCP 快速打开、窗口缩放、增加初始拥塞窗口大小等优化手段。内容有点偏理论,还是需要多多实践,才能合理掌握各种优化手段。


参考文献:

  1. 《Web性能权威指南》
  2. 《TCP/IP详解,卷1:协议》
  3. 浅谈TCP优化
  4. TCP慢启动中cwnd的增长问题? - one no的回答 - 知乎
为什么要开发Tcpdive        在过去的几年里,随着移动互联网的飞速发展,整个基础网络已经发生了翻天覆地的变化。  用户接入网络的方式,除了宽带和光纤之外,还有2G/3G/4G/WiFi,5G也已经在路上了。  作为使用范围最广的传输层协议,TCP诞生于固网时代,在设计之初并没有考虑到上述种种情况,  这导致了它在某些场景下,性能并不是最优的。因此大多数的CDN厂商和一些规模较大的互联网公司都会  进行TCP协议的优化,以提供更好的用户体验,如更快的访问速度,更低的访问失败率,更流畅的视频播放等。 而当我们尝试优化TCP协议时,却面临着不少难点: 可用的工具少。  和TCP相关的工具,比如tcpdump,netstat和ss,虽然很好用,但是使用场景并不是TCP协议的性能评测,  能够提供的性能信息实在有限。 依靠个人感觉,进行盲试。  不知道瓶颈在哪,盲目修改,或者直接套用已有的优化方法。  盲目修改常导致徒劳无功,直接套用现成的方法,由于大家的应用场景不尽相同,也不一定有效。 测试成本高。  对TCP协议的性能评测主要采用两种方法。  一种是通过对上层应用的测试,来评估TCP协议的性能。这种方法的评价指标有限,而且是上层应用相关的。  另一种是依靠第三方测试服务。这种方式的样本量有限,且成本较高。 无法准确地评价优化效果。  上述的两种测试方法,都涉及到应用层面,因此测量的不仅仅是TCP协议本身,还参杂了干扰因素。   Tcpdive的设计目标        针对上述问题,我们决定设计一个专门的TCP协议性能评测工具,也就是Tcpdive。  之所以起这个名字,是因为dive有深入研究的意思:) Tcpdive具有一些特性,实际上也是我们的设计目标: 对TCP协议的性能进行较为全面的刻画,有助于发现瓶颈。  如此一来,就能找到痛点,不用再盲目地进行优化。 易于部署和使用,无需改动生产环境,使用成本低。  这一点非常重要,因为不需要修改内核或者应用程序,比较容易推广。 独立于上层应用,能够准确地评价优化效果。  直接对TCP协议的性能进行刻画,而不依赖于具体的应用。  因此能够排除上层应用的干扰,量化地评价优化效果。   Tcpdive的基本原理        Tcpdive是基于linux内核的探测点机制,使用systemtap脚本语言和内嵌C代码来实现的。  通过定义几类相互关联的探测点和库函数,来收集和处理运行中内核的数据,以及修改内核的处理逻辑。         为什么要基于systemtap呢?systemtap的神奇之处在于,不修改内核的情况下就能获取内核中的任何信息, 还可以修改内核的处理逻辑。所以虽然被它虐了千百遍,但还是觉得这套探测点机制非常有用。当然它也不是 十全十美的,比如作为一种调试语言,它是够用的,但是把它用作一种开发语言,则会遇到不少问题。通过不 断的尝试,大多数问题最终都获得比较好的解决。         目前Tcpdive已经部署到作为流量入口的负载均衡服务器上,在新浪的线上环境7*24h运行,可以说是比较稳定的。 Tcpdive的主要功能 作为一个TCP协议的性能评测工具,Tcpdive提供了大量的性能指标,从以下维度来对每条TCP连接进行刻画: 传输情况 丢包和重传 拥塞控制 HTTP处理   传输:   损失和重传: 拥塞控制: HTTP 处理:     标签:tcpdive
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值