TCP的高性能机制

标签: tcp 性能 | 发表时间:2021-06-02 07:46 | 作者:zchanglin
出处:https://juejin.cn/frontend

之前介绍了 TCP 的报文格式(《TCP 协议基本特性》),TCP 的连接管理,学习了 TCP 如何建立连接,释放连接以及一些网络安装方面的问题,现在还剩下 TCP 的几个关键机制,主要是 TPC 的延迟应答和捎带应答、超......

之前介绍了 TCP 的报文格式( 《TCP 协议基本特性》),TCP 的连接管理,学习了 TCP 如何建立连接,释放连接以及一些网络安装方面的问题,现在还剩下 TCP 的几个关键机制,主要是 TPC 的延迟应答和捎带应答、超时重传、快重传和快恢复、滑动窗口机制、拥塞避免算法;然后最后还记录了 TCP 的粘包问题和解决方案!

TCP 实现的可靠传输其实依赖于确认应答机制,也就是接收方每次接收完数据之后会回发一个 ack 确认号,代表自己下次期望收到的序号,意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发。 TCP 数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节 流中每个字节的编号。一个 TCP 数据包中包含多个字节流的数据(即数据段),而且每个 TCP 数据包中的数据大小不一定相同。在建立 TCP 连接的三次握手 过程中,通信双方各自已确定了初始的序号 x 和 y,TCP 每次传送的报文段中的序号字段值表示所要传送本报文中的第一个字节的序号。

TCP 的确认应答

TCP 提供的确认机制,可以在通信过程中可以不对每一个 TCP 数据包发出单独的确认包(Delayed ACK 机制),而是在传送数据时,顺便把确认信息传出, 这样可以大大提高网络的利用率和传输效率。同时,TCP 的确认机制,也可以一次确认多个数据报,例如,接收方收到了 201,301,401 的数据报,则只 需要对 401 的数据包进行确认即可,对 401 的数据包的确认也意味着 401 之前的所有数据包都已经确认,这就是延迟应答,这样也可以提高系统的效率。

再说说捎带应答,TCP 的确认应答和回执数据可以通过一个包发送。

TCP 的超时重传

若发送方在规定时间内没有收到接收方的确认信息,就要将未被确认的数据包重新发送。接收方如果收到一个有差错的报文,则丢弃此报文,并不向发送方 发送确认信息。因此,TCP 报文的重传机制是由设置的超时定时器来决定的,在定时的时间内没有收到确认信息,则进行重传。这个定时的时间值的设定非常重要,太大会使包重传的延时比较大,太小则可能没有来得及收到对方的确认包发送方就再次重传,会使网络陷入无休止的重传过程中。接收方如果收到 了重复的报文,将会丢弃重复的报文,但是必须发回确认信息,否则对方会再次发送。

但是主机 A 未收到 B 发来的确认应答, 也可能是因为 ACK 丢失了;因此主机 B 会收到很多重复数据。那么 TCP 协议需要能够识别出那些包是重复的包,,并且把重复的丢弃掉。这时候我们可以利用前面提到的序列号, 就可以很容易做到去重的效果。

超时时间如何确定?

TCP 为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间:Linux 中 (BSD Unix 和 Windows 也是如此),超时以 500ms 为一个单位进行控制,每次判定超时重发的超时时间都是 500ms 的整数倍,如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传如果仍然得不到应答,等待 4*500ms进行重传。依次类推以指数形式递增,累计到一定的重传次数,TCP 认为网络或者对端主机出现异常,强制关闭连接

TCP 快速重传(冗余 ACK)

有了超时重传机制为什么还出现了快速重传呢?其实这也是 TCP 为了效率的一种保障,每当比期望序号大的失序报文段到达时,发送一个冗余 ACK,指明下一个期待字节的序号。

超时重传是底线,是功能性的,但是快重传是建立在超时重传上的,为了效率的提高

TCP 流量控制

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制 (Flow Control);

在通信过程中,接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,即接收窗口 rwnd (接收方设置确认报文段的窗口字段来将 rwnd 通知给发送方), 发送方的发送窗口取接收窗口 rwnd 和拥塞窗口 cwnd 的最小值。接收窗口也就是接收方的接收缓冲区,拥塞窗口简单来说就是网络堵塞了,那就是说明在这个网络中使用网络带宽的主机很多,或者占用了很多资源,导致发送缓慢,那么这就是一个网络拥塞的情况

TCP 首部中,专门有一个窗口大小的字段用来通知窗口大小。接收主机将自己可以接收的缓冲区大小放人这个字段中通知给发送端。这个字段的值越大,说明网络的吞吐量越高。不过,接收端的这个缓冲区一旦面临数据溢出时,窗口大小的值也会随之被设置为一个更小的值通知给发送端,从而控制数据发送量。也就是说,发送端主机会根据接收端主机的指示,对发送数据的量进行控制。这也就形成了一个完整的 TCP 流控制 (流量控制)。

从图中可以看到,如果过了重发时间还没有收到窗口的更新通知,会发送一个探测报文去探测接收方的窗口。

滑动窗口虽然只能往右滑,但是可能变大,也可能变小,也可能是 0;收到第一个 ACK 后,滑动窗口向后移动,继续发送第五个段的数据,依次类推,操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉;窗口越大,则网络的吞吐率就越高;

TCP 拥塞控制

因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发送大量的数据,是很有可能引起雪上加霜的。一般来说,计算机网络都处在一个共享的环境。因此也有可能会因为其他主机之间的通信使得网络拥堵。在网络出现拥堵时,如果突然发送一个较大量的数据,极有可能会导致整个网络的瘫痪看看 TCP 是如何解决这个问题的呢?

TCP 引入了慢启动机制:先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;

那么慢启动和拥塞避免的算法如下图所示:

cwnd 指的是一个报文段(最大报文段长度 MSS),最开始发一个报文段然后呈指数式增长到 ssthresh 初始值,这就是慢启动,然后执行加法增大,也就是拥塞避免阶段,达到阈值的时候变会触发快重传,此时降到新的 ssthresh 值,即为拥塞时的一半,这就是快恢复策略!当 TCP 通信开始以后,网络吞吐量会逐渐上升,但是随着网络拥堵的发生吞吐量也会急速下降。于是会再次进人吞吐量慢慢上升的过程。因此所谓 TCP 的吞吐量的特点就好像是在逐步占领网络带宽的感觉。

TCP 粘包问题

首先要明确,粘包问题中的” 包” 是指的应用层的数据包。

在 TCP 的协议头中,没有如同 UDP 一样的” 报文长度” 这样的字段,但是有一个序号这样的字段。站在传输层的角度,TCP 是一个一个报文过来的,按照序号排好序放在缓冲区中。站在应用层的角度,看到的只是一串连续的字节数据,那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分是一个完整的应用层数据包

那么如何避免粘包问题呢? 归根结底就是一句话,明确两个包之间的边界:

  • 对于定长的包,保证每次都按固定大小读取即可;例如对于一个结构体 struct,是固定大小的,那么就从缓冲区从头开始按 sizeof(struct) 依次读取即可;
  • 对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包的结束位置;
  • 对于变长的包,还可以在包和包之间使用明确的分隔符 (应用层协议,是程序猿自己来定的,只要保证分隔符不和正文冲突即可);

对于 UDP 是否也存在” 粘包问题” 呢?对于 UDP,如果还没有上层交付数据,UDP 的报文长度仍然在。同时,UDP 是一个一个把数据交付给应用层,就有很明确的数据边界。站在应用层的角度,使用 UDP 的时候,要么收到完整的 UDP 报文,要么不收,不会出现” 半个” 的情况。

相关 [tcp 性能] 推荐:

TCP的高性能机制

- - 掘金 前端
之前介绍了 TCP 的报文格式(《TCP 协议基本特性》),TCP 的连接管理,学习了 TCP 如何建立连接,释放连接以及一些网络安装方面的问题,现在还剩下 TCP 的几个关键机制,主要是 TPC 的延迟应答和捎带应答、超....... 之前介绍了 TCP 的报文格式( 《TCP 协议基本特性》),TCP 的连接管理,学习了 TCP 如何建立连接,释放连接以及一些网络安装方面的问题,现在还剩下 TCP 的几个关键机制,主要是 TPC 的延迟应答和捎带应答、超时重传、快重传和快恢复、滑动窗口机制、拥塞避免算法;然后最后还记录了 TCP 的粘包问题和解决方案.

记一次关于TIME_WAIT TCP连接数的性能优化

- - Juven Xu
一天下午3点多,我们的OPS打电话给我(你懂的,OPS打电话过来不会是请你喝咖啡),我连忙接起电话,电话那头的声音很急迫:“content集群有报警,CPU负载已经到了50多,你快过来一起看看”,我挂了电话连忙赶过去,OPS坐在另一幢楼的同一层,好在两幢楼是相连的,过去很方便. 边走我心里边嘀咕,content集群实际上是一个反向代理,上面配置了上百条apache http url rewrite 规则,每条规则的作用就是把一个url路径转换成另外一个url路径,发送到某个后端的集群上,然后把返回结果转出去,几乎没有计算量,不应该有高负载啊.

高性能网络编程7--tcp连接的内存使用

- - CSDN博客互联网推荐文章
当服务器的并发TCP连接数以十万计时,我们就会对一个TCP连接在操作系统内核上消耗的内存多少感兴趣. socket编程方法提供了SO_SNDBUF、SO_RCVBUF这样的接口来设置连接的读写缓存,linux上还提供了以下系统级的配置来整体设置服务器上的TCP内存使用,但这些配置看名字却有些互相冲突、概念模糊的感觉,如下(sysctl -a命令可以查看这些配置):.

tcp/ip调优

- Lucseeker - 在路上
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;. 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;.

浅谈TCP优化

- - 火丁笔记
很多人常常对 TCP优化有一种雾里看花的感觉,实际上只要理解了TCP的运行方式就能掀开它的神秘面纱. Ilya Grigorik 在「 High Performance Browser Networking」中做了很多细致的描述,让人读起来醍醐灌顶,我大概总结了一下,以期更加通俗易懂. 传输数据的时候,如果发送方传输的数据量超过了接收方的处理能力,那么接收方会出现丢包.

TCP报文结构

- - 互联网 - ITeye博客
一、TCP报文结构如下:.  固定首部长度为20字节,可变部分0~40字节,各字段解释:. source port number:源端口,16bits,范围0~65525. target port number:目的端口,16bits,范围同上. sequence number:数据序号,32bits,TCP 连接中传送的数据流中的每一个字节都编上一个序号.

TCP 状态变化

- - 互联网 - ITeye博客
关闭socket分为主动关闭(Active closure)和被动关闭(Passive closure)两种情况. 前者是指有本地主机主动发起的关闭;而后者则是指本地主机检测到远程主机发起关闭之后,作出回应,从而关闭整个连接. 将关闭部分的状态转移摘出来,就得到了下图:. 通过图上,我们来分析,什么情况下,连接处于CLOSE_WAIT状态呢.

TCP/IP分享——链路层

- Goingmm - 弯曲评论
在张国荣自尽8周年纪念日,也就是愚人节的前几十分钟,终于把第二章弄完了. 首席似乎不是特别有空,我就斗胆在这里自己发了,从前面2期的反响来看,相当热烈,我也是摆出一副要杀要剐,悉听尊便的架势,这可能是受最近流行霸气外露的影响,批评几句又伤不了皮毛,也影响不了我的工作和正常生活,只要给大家带来快乐,我就很开心,似乎历史上很多想法都是在争吵中诞生的.

TFO(tcp fast open)简介

- chenqj - pagefault
原创文章,转载请注明: 转载自pagefault. 本文链接地址: TFO(tcp fast open)简介. 这个是google的几个人提交的一个rfc,是对tcp的一个增强,简而言之就是在3次握手的时候也用来交换数据. 这个东西google内部已经在使用了,不过内核的相关patch还没有开源出来,chrome也支持这个了(client的内核必须支持).

TCP/IP重传超时--RTO

- dennis - 一个故事@MySQL DBA
Shared by 子非鱼 安知余(褚霸). 概述:本文讨论主机在发送一个TCP数据包后,如果迟迟没有收到ACK,主机多久后会重传这个数据包. 主机从发出数据包到第一次TCP重传开始,RFC中这段时间间隔称为retransmission timeout,缩写做RTO. 本文会先看看RFC中如何定义RTO,然后看看Linux中如何实现.