TCP RTT与TCP RTO关系详解

1,TCP的RTT和TCP的RTO的定义

1.1,什么是TCP的RTT

RTT是Round Trip Time的缩写,TCP的RTT意思是指TCP报文发送完成的时刻到接收到该报文对应的ACK报文的时刻的差值。我们知道二个主机之间的路由路径是可以动态变化的,所以二个主机之间的网络延时不仅会因为网络状态的不一样而动态变化经,还会随着路由路径的变化而变化。所以二个主机之间的RTT也不是一成不变的,是一个动态变化的值。
TCP为每一条TCP连接保持一个独立的当前RTT的值。

BTW:往返时延RTT只对传输层的TCP协议才重要,因为TCP要根据平均往返时延RTT的值来设置超时计时器的超时时间以及合适的接收窗口rwnd。UDP没有确认和重传机制,RTT对于UDP来说没有什么意义。

1.2,什么是TCP的RTO

我们都知道TCP使用超时重传的机制来保证网络丢包发生,导致没能收到确认ACK时,能重传报文,来提供端到端的可靠传输的机制。那么多长时间后执行重传呢?这就引入了RTO。RTO是Retransmission Time Out的缩写,定义了TCP重传超时时间,即定义了TCP超时重传定时器的超时时长,指从数据发送时刻算起,超过这个时间便对本报文执行重传。

  • RTO太大了
    重发就慢,丢了还要过很久才重发,导致TCP连接没有充分利用网络,网络的利用率低,进而导致TCP端到端传输的延时长,性能差。
  • RTO太小了
    重发得太快,会导致没有丢的包就重发。于是网络上存在大量的无意义的重发报文,一来占用大量带宽会,二来会增加网络拥塞,会导致更多的超时,然后更多的超时双导致更多的重发。

所以定义一个合适的RTO非常重要,在理想网络中,RTO略微大于RTT是一个能充分利用网络能力的最理想的定义,但实际网络中,就比这个复杂得多了。

2,TCP的当前RTT和RTO的计算

在稳定的网络中,RTT几乎保持不变,那么很简单,只要测定一次RTT后面就一直用这个值就好了。但在实际的网络中,RTT通常是动态变化的,一会大一会小,所以如何计算出一个合适的最能反应当前网络的RTT就成了RTT计算的关键。

2.1,开始讲RTT计算算法前,我们先理解一下TCP里对RTT进行采样的流程

在TCP网络中,并不是对每一个TCP报文都进行RTT计算采样的。只对部分TCP报文进行RTT计算采样。这个采样方法的定义稍微有点抽象:在任何时候,对每一个TCP连接测量且仅测量一次RTT值,则在发送一个报文时,如果给定连接正在测量RTT值(测量RTT的定时器已经被使用),则不对该报文测量RTT
如下图:

  • RTT #1:
    发送报文1到收到对应的ACK(报文2)的时间差,这个很好理解。
  • RTT #2:
    发送报文3到收到对应的ACK(报文5)的时间差,这个很好理解。但这里我们可以注意到报文4并没有被用于计算RTT,对应为:在报文3发送出去之后收到对应的ACK(报文5)之间由左侧主机发起的所有TCP报文(报文4)都不会做RTT采样计算
  • RTT #3:
    送报文6到收到对应的ACK(报文10)的时间差,这个很好理解。但这里我们可以注意到报文4并没有被用于计算RTT,对应为:在报文6发送出去之后收到对应的ACK(报文10)之间由左侧主机发起的所有TCP报文(报文7和报文9)都不会做RTT采样计算

在这里插入图片描述

2.2,最初始的TCP RTT和RTO计算方法及存在的问题

  • 计算方法
    RTT = 收到ACK的时间 - 发送报文的时间
    然后我们会在得到每次RTT采样结果时以用以公式计算出当前RTT,称为SRTT( Smoothed RTT),按网络RTT变化的快慢不同,其中 alpha 可以取不同的值,以适应不同的网络。alpha值取得小,则当前RTT的权重大,可以快速适应 RTT 的微小变化,但受到RTT的暂时波动的影响比较大,alpha值取得小,则历史的SRTT的权重大,当前RTT的权重小,SRTT的变化曲线更稳定,比较平滑,不易受RTT的暂时波动的影响,但响应不够快,在RTT变化比较快的网络中无法快速适应RTT的真正的变化。所以alpha的取值是一个经验值,在不同的网络中最好可以使用不同的值。通常alpha可以取0.8到0.9之间的一个数字。
  SRTT = ( alpha * SRTT ) + ((1 - alpha) * RTT)

(第一次迭代的时候SRTT的初始值为最近的一次RTT)
这样用SRTT和RTT做加权运算,就可以平滑的处理这个SRTT,不会让当前RTT(即SRTT)总是在跳变,但又可以根据当前的RTT做适时的调整。

根据Linux的实现, TCP_RTO_MAX为120秒,TCP_RTO_MIN为200毫秒,RTO的初始值为1秒, beta一般取值为1.3到2.0之间

 RTO = min [ TCP_RTO_MAX,  max [ TCP_RTO_MIN,   (beta * SRTT) ]  ]

在SRTT开始计算后,可以用以上公式算出RTO。

  • 存在的问题
    在重传发生时,会发生如下图的问题,
    如果你用新传的包做为起点,则可能会导致采样出来的RTT会远大于实际RTT; 如果你用重传的包做为起点,则可能会导致采样出来的RTT会或者远小于实际RTT。
    在这里插入图片描述

2.3,TCP RTT和RTO的计算方法的改进

因为初始算法存在的种种问题,提出了以下改进:

  • 改进一:不对重传报文做RTT采样
    不对重传报文做RTT采样,只对新传的报文做RTT采样。这样就规避了上面说到的重传发生时,到底是使用重传那个报文还是使用新传的报文做为RTT地采样开始点的问题。但这样子做引入一个问题,就是当RTT在某一时刻突然变大时,即网络产生了一个比较大的延时,这个延时会导致所有的包(因为之前的RTO很小,所以在TCP重传定时器超时时,所有的报文都没有收到对应的ACK)都发生超时重传,但是因为重转的包不算RTT,所以,RTO就不会被更新,进而引发TCP重传定时器还是一个很上的值,那么会进一步发生重传,网络就会一下子进入拥塞状态,导致网络的吞吐量性能急剧下降。所以引入了以下的改进二。
  • 改进二:一旦发生重传,就对现有的RTO值翻倍
    一旦发生重传,就对现有的RTO值翻倍,以避免大量的重传引发的网络拥塞。

这种算法存在的问题:
1) 参数alpha值不好取舍,如上面所述:alpha值取得小,则当前RTT的权重大,可以快速适应 RTT 的微小变化,但受到RTT的暂时波动的影响比较大,alpha值取得小,则历史的SRTT的权重大,当前RTT的权重小,SRTT的变化曲线更稳定,比较平滑,不易受RTT的暂时波动的影响,但响应不够快,在RTT变化比较快的网络中无法快速适应RTT的真正的变化。
2)网络较差情况,RTO持续翻倍,重发的速率急剧减缓,导致TCP传输的效率和性能劣化得非常快,网络利用率非常低下。

2.4,TCP RTT和RTO的计算方法的进一步改进(Linux的当前实现)

为了解决上述的问题,又引入了deviation RTT的概念(RFC6289),则这个算法引入了最新的RTT的采样值和平滑过的SRTT的值之间的差距做因子来计算,如果差距大,则DevRTT主导了计算结果,如果差距小,则SRTT主导了计算结果。

SRTT = SRTT + alpha*(RTT – SRTT)

DevRTT = (1-beta)*DevRTT + beta*(|RTT-SRTT|)

RTO= micro * SRTT + delta *DevRTT

在Linux实现里,alpha = 0.125,beta = 0.25, micro = 1,delta = 4

这样就解决了alpha不好取值的问题,达到了既平滑又能快速感知RTT变化的目标。

猜你喜欢

转载自blog.csdn.net/meihualing/article/details/129473851
tcp