你是否注意到,你的网络连接有时会变得很快,但随后又会突然变慢,而实际上并没有任何明显的变化发生?某个请求在某一时刻可能需要20毫秒才能完成,而在下一刻却可能需要80毫秒,甚至有时候根本无法完成。人们经常使用RTT、抖动和丢包这些术语来解释这种现象,但实际上它们之间的关联往往很容易被忽视。
在本文中,我们将把RTT、抖动和丢包看作是同一个时间测量系统中的不同组成部分,而不是独立的指标。首先,你会了解RTT的含义以及它为什么会随时间发生变化;接着,你会学习到抖动是如何作为相对于基线的额外延迟而出现的;最后,你会看到TCP是如何利用这些时间测量信息来判断延迟何时会发展成丢包现象的,其中重点会放在TLS协议以及后量子时代TLS握手过程中的具体行为上。
我们的目标很简单:就是要弄清楚时间测量数据是如何被用来做出决策的。
目录
RTT(往返时间)
在讨论延迟、抖动或数据包丢失等问题之前,我们首先需要明确什么是RTT。如果对RTT的概念不够清楚,那么后续提到的所有内容都会让人感到困惑。
RTT代表往返时间。它是指数据包从客户端发送到服务器,再由服务器返回给客户端所花费的总时间。
假设你发送了一个数据包,并在50毫秒后收到了回复,那么RTT就是50毫秒。这就是RTT的基本定义。
但关键在于:RTT并不是一个固定的数值。它会不断变化。即使是与同一台服务器进行通信,每次发送数据包时,RTT也可能有所不同。造成这种变化的原因有很多,比如:
-
数据包在队列中等待
-
暂时性的网络拥堵
- 路由器内部的调度机制
- 同一路径上存在的其他背景流量
假设你连接到了谷歌服务器,并现在发送了一个数据包。实际上,我们可以使用一些简单的工具来测量RTT。其中一种常用的方法是ping命令,该命令会发送一个数据包,并测量回复信号返回所需的时间。
ping -n 1 google.com

通过这个命令,你会在50毫秒后收到回复。
RTT = 50 毫秒
这个数值是真实的,但它并不完整。单次测量的RTT结果无法告诉我们:是网络路径本身需要50毫秒的时间,还是这条路径实际上更快,只是数据包在传输过程中遇到了短暂的延迟。
例如,实际的路程延迟可能是49毫秒,而另有1毫秒是数据包在队列中等待所花费的。仅凭一次RTT测量结果,我们无法区分这些不同的因素。只有通过多次测量,才能获得准确的RTT数值。
因此,让我们进行多次RTT测量吧。
通过这些测量结果,我们可以发现一些规律:
最小RTT ≈ 18 毫秒
最大RTT ≈ 19 毫秒
平均RTT ≈ 18 毫秒
正因为如此,RTT并不是通过一次数据包传输就能立刻得知的数值。它需要我们通过多次测量来获得。
当反复测量RTT时,所得数值并不一致。有些测得的RTT值较低,有些较高,而还有一些值会因为暂时的网络状况而突然升高。
你可能会看到这样的数据序列:低、低、低、低、高。正因为如此,我们需要一个参考点,我们可以将这个参考点称为“稳定值”。如果没有这个参考点,所有的RTT数值都会显得令人困惑,我们也无法判断某个数据包传输速度变慢是因为路径本身存在问题,还是因为发生了某些临时性的网络故障。
基线RTT
这个稳定值就是基线RTT。基线RTT指的是经过长时间观测后所得到的最低RTT值。这个数值代表了没有受到任何临时性因素影响时的RTT情况。
例如,在上面的例子中,我们反复测量后得到的最低RTT值为18毫秒,那么18毫秒就是我们的基线RTT。你可以把基线RTT理解为给定路径上可能出现的最快传输速度,它代表了网络处于正常状态时的情况——此时数据包不会在队列中等待,也不会出现拥塞或重传现象。
换句话说,基线RTT反映了在没有异常情况发生时网络的真实传输能力。这通常也是最理想的情况,因为这种情况下不会受到任何临时性因素的影响。
为什么基线RTT如此重要
一旦我们得到了基线RTT,那么各个单独测得的RTT数值就不再显得随机无序了。我们可以清楚地判断出某个RTT值是接近基线RTT的,还是高于预期的值,又或者是否是因为暂时的网络状况而导致了额外的延迟。
如果没有基线RTT作为参考,每一个RTT数值都孤立存在,比较这些数值也就变成了猜测而已。但有了基线RTT之后,RTT数值就有了实际的意义,其变化也变得显而易见了,我们终于能够分析出导致RTT增加的原因,而这种原因往往也会引发抖动现象。
这就是我们接下来要讨论的内容:究竟是什么导致了RTT的增加,而这种增加又自然而然地会导致抖动现象的发生。
什么是抖动?
现在我们来谈谈抖动。一旦我们知道了基线RTT的值,一些重要的问题就变得清晰起来了——大多数情况下,测得的RTT值都是高于基线RTT的。
那么下一个自然的问题就是:如果基线RTT代表的是网络处于正常状态下的情况,那么为什么在其他测量中还会出现RTT增加的现象呢?
这种额外的延迟现象就是我们所说的抖动。
抖动的真正含义
抖动其实就是加在基线RTT之上的额外延迟。简单来说,基线RTT反映了网络在正常状态下的传输能力,而抖动则说明了当网络变得繁忙时,数据包会遇到哪些额外的延迟问题。
因此,每一个实际测得的RTT值都可以用以下公式来表示:实际测得的RTT = 基线RTT + 额外延迟
示例

基准RTT为18毫秒。那额外的延迟其实就是抖动。
有两条重要的要点需要记住。首先,抖动总是正值,因为数据包的传输延迟不会小于基准RTT;其次,基准RTT起到了参考点的作用,也就是说,抖动是相对于这个基准值而言才存在的。如果没有基准值,抖动就没有任何意义了。
抖动的来源
当数据包在网络中不能立即被传输时,就会产生抖动。
这种情况通常由以下原因导致:
-
数据包在队列中等待
-
路由器在转发数据包之前会延迟处理它们
-
链路出现临时性拥塞
-
数据包丢失后需要重新传输
这些因素并不会持续存在,它们时有时无。正因如此,抖动才会表现为不规律、间歇性的现象——有时候抖动很小,而有时候则会突然增大。
抖动能告诉我们什么
现阶段,抖动仍然只是一种观察结果。它告诉我们网络传输的稳定性如何,以及数据包出现额外延迟的频率是多少。但我们还没有根据这些信息做出任何决策,我们只是在描述网络的实际运行情况而已。
TCP是如何获取RTT和抖动数据的
我们已经了解到:
-
RTT会随时间发生变化
-
基准RTT为我们提供了一个参考值
-
抖动可以解释那些额外的延迟现象
因此,到目前为止,我们只是在观察网络的行为。但现在出现了一个新的问题:既然RTT会不断变化,而且延迟和抖动确实存在,那么究竟是谁在监测这些数据呢?更重要的是,谁来决定“等待是正常的”还是“等待已经成了问题”呢?
这时,TCP就派上了用场。TCP就是那个负责监测这些时间变化,并根据这些信息来决定下一步该做什么的组件。
TCP并不会提前知道RTT的值
TCP在开始连接时,并不知道路径的长度、网络的稳定性,也不知道会遇到多大的延迟。它是在连接运行过程中动态地获取这些信息的。
TCP是在连接运行期间通过观察时间变化来获取所有这些数据的。每次TCP发送数据并收到确认响应时,它就能获得一个RTT测量值。随着时间的推移,这些测量值会被用来形成预测结果。
为了理解这些时间数据,TCP会维护两个内部数值,这两个数值总结了它迄今为止所获得的全部信息。
SRTT(平滑RTT)
SRTT是指TCP预期中的平均传输延迟值。它既不是最小的RTT值,也不是简单的平均值,而是一个经过平滑处理的数值,代表了TCP根据近期测量数据所预测出的正常传输延迟水平。这意味着最近的测量结果更为重要,而较早的测量数据则逐渐失去参考意义。
正因如此,SRTT不会因为某个延迟数据包的存在而发生突变。相反,它会随着网络状况的变化而逐渐进行调整。
例如,假设TCP检测到了以下RTT数值(单位为毫秒):48、50、49、51、50。
那么TCP会将这些数值平滑处理,得出一个稳定的平均值,比如:SRTT ≈ 50毫秒。
你可以将SRTT理解为:TCP根据最近的网络运行情况判断出的、认为合理的延迟值。它实际上是一种基于历史数据的加权平均数,因此会更倾向于最近的RTT数值。
RTTVAR(RTT变化幅度)
RTTVAR能够告诉TCP“RTT的变化程度有多大”。现在我们来比较两种情况。
RTT稳定的情况
RTT数值示例:49、50、51、50
由于这些数值彼此接近,因此变化幅度很小,RTTVAR的值也会保持较低水平,TCP对其测得的延迟时间也很有信心。
RTT不稳定的情况
RTT数值示例:50、52、90、48
在这种情况下,RTT的突然变化会导致波动幅度增大,从而使RTTVAR的值上升,TCP也会对其测得的延迟时间产生怀疑。
为什么TCP需要这两者
仅依靠SRTT是不足以让TCP做出可靠的延迟判断的。如果TCP只知道RTT约为50毫秒,它仍然无法判断网络延迟是否稳定,或者突发性的延迟现象是否常见。
RTTVAR通过反映RTT随时间的变化情况来填补这一空白。虽然SRTT告诉TCP在正常情况下应该预期什么样的延迟值,但RTTVAR则让TCP知道对这一预测应该有多大的信心。
在这个阶段,TCP仍在“学习”,而不是进行最终的判断。它正在构建一个关于网络延迟特性的模型。
目前,网络会带来各种延迟变化;基线RTT为测量提供了稳定的参考依据;抖动则可以解释那些额外的延迟现象;而TCP则是通过SRTT和RTTVAR来观察并分析所有这些数据的。
只有在这个阶段之后,TCP才会开始做出决策。而其中的一项决策就是判断数据包是否已经丢失。
TCP如何判断数据包是否丢失
现在,既然TCP已经了解了RTT通常的变化范围,它就必须回答一个重要的问题:我应该等待多久才能认定某个数据包已经丢失?
这就是数据包丢失检测机制发挥作用的地方。
TCP永远看不到数据包被丢弃的过程
TCP无法看到路由器、队列或连接状态,也不知道数据包的具体去向。它所能感知的只有时间流逝。TCP发送数据后,就会等待确认信号的到来。
如果确认信号及时到达,那么一切就正常;如果没有收到确认信号,TCP就必须决定接下来该采取什么行动。
重传超时时间(RTO)
为了做出这个判断,TCP会使用“重传超时时间”这一指标。RTO并不是随机确定的,而是根据TCP之前收集到的网络延迟数据计算得出的。
从概念上来说,RT的计算公式如下:
RTO = SRTT + max(𝐺, 4 × RTTVAR)
在这里,SRTT表示预期的延迟时间,而RTTVAR则增加了额外的缓冲时间以弥补网络延迟的不稳定性。因此,RTO实际上反映了TCP根据网络延迟的不确定性所愿意等待的时间长度。
假设TCP检测到SRTT为50毫秒,RTTVAR为5毫秒,那么RTO的值就是70毫秒。
RTO = 50 + 4 × 5
RTO = 70毫秒
在这种情况下,TCP的行为规则就变得很简单了:
-
如果确认应答在60毫秒后到达,就被视为延迟。
-
如果确认应答在75毫秒后到达,则说明数据包已经丢失。
网络环境并没有改变,数据包本身也没有变化,只有到达时间发生了变化,而这种变化就会导致TCP做出不同的处理决策。
延迟与数据包丢失
TCP的逻辑非常简单:如果数据包在RTO期限之前到达,就被视为正常延迟;如果超过了RTO期限仍未到达,TCP就会认为该数据包已经丢失。
这就引出了一个重要的结论:数据包丢失其实是一种基于时间判断的结果,并非必然发生的事情。数据包有可能之后才会到达,但一旦RTO期限过去,TCP就会立即采取相应的处理措施。
抖动如何导致数据包丢失
这种机制与网络中的抖动现象密切相关。只要抖动幅度保持在RTO范围之内,数据包虽然会延迟到达,但仍然不会被视为丢失;然而当抖动幅度过大,导致延迟时间超过了RTO的限制时,TCP就会将这种延迟视为数据包丢失。
因此,数据包丢失并不一定意味着数据包真的消失了,很多时候它只是表示网络延迟变得过于不可预测而已。
结论
通过以上分析我们可以看出,RTT、抖动和数据包丢失其实并不是彼此独立的网络指标,它们共同描述了同一个网络延迟现象的不同方面:
-
RTT反映了通信过程通常所需的时间。
-
稳定的RTT值可以为网络性能提供可靠的参考依据。
-
抖动解释了为什么网络延迟会发生变化。
-
只有当延迟的变化超出了协议所能容忍的范围时,才会出现数据包丢失的情况。
一旦弄清了这些原理,我们就会发现网络中的各种现象其实都有其背后的逻辑原因,而不再显得那么随机不可预测了。归根结底,这一切都是与时间延迟、不确定性以及TCP的决策机制有关的。
![RTT [图片来源:speedvitals.com ]](https://cdn-images-1.medium.com/max/1600/1*tKeOZNVYvkDuXMl4WytN5Q.jpeg)