为什么我们需要把服务器放到距离用户最近的地方?其中的一个原因是为了达到较低的延迟。当需要发送大量小数据包时,这变得非常敏感。传输大文件,例如视频,接收第一个字节时,会有延迟,但接下来会怎么样呢,是不是变得很平滑了呢?
一个比较大误解是,当我们用tcp发送数据包的时候,例如http,带宽是独立于延迟的。但是,带宽是延迟和时间函数。我们接下来看看为什么这么说。
握手
客户端和服务器发送数据之前,需要进行TCP握手和TLS握手
TCP需要三次握手建立一个新的连接
- 发送方生成一个随机数‘X’发用一个SYN包到接收方
- 接收方对‘X’加一,生成一随机数‘Y’,返回一个SYN/ACK包
- 发送方增加‘X’、‘Y’,应答一个ACK包和应用数据。
- ‘x’、‘Y’用于保证TCP数据包的序列,确保没有间断
握手引入了一个完整的往返过程,这取决于底层网络的延迟。TLS握手还需要两次往返。在TLS连接打开之前,不能发送任何应用程序数据,这意味着在此之前您的带宽为零。往返时间越短,建立连接的速度就越快。
流控
流控制是一种回退机制,用于防止发送方压倒接收方。
接收方将等待应用程序处理的传入TCP数据包存储到接收缓冲区中。
无论何时接收方接收到数据包,它都会将缓冲区的大小反馈给发送方。发送方,如果它尊重协议,避免发送更多的数据,可以容纳在接收方的缓冲区。
这种机制与应用程序级别的速度限制并没有太大的不同。但是,TCP在连接级别上限制速率,而不是在API或IP地址上限制速率。 发送方和接收方之间的往返时间(RTT)越低,发送方就越快地根据接收方的容量调整其输出带宽。
拥塞控制
TCP不仅可以保护接收方,还可以保护底层网络。 发送方如何知道底层网络的可用带宽是多少?估计它的唯一方法是通过实际测量。
其思想是发送方维护一个所谓的“拥塞窗口”。“该窗口表示未完成的数据包的总数,可以发送而无需等待来自另一方的确认。”接收器窗口的大小限制了拥塞窗口的最大大小。拥塞窗口越小,在任何给定时间可以传输的字节就越少,使用的带宽也就越少。
当建立新连接时,拥塞窗口的大小被设置为系统默认值。然后,对于每一个被确认的包,窗口的大小会呈指数级增长。这意味着我们不能在连接建立后立即使用网络的全部容量。同样,往返时间越短,发送方就越快开始利用底层网络的带宽。
如果丢了包怎么办?当发送方通过超时检测到错过的确认时,一种称为“拥塞避免”的机制就会启动,拥塞窗口大小就会减小。从那时起,时间将使窗口大小增加一定的数量,而超时将使窗口大小减少另一个数量。
如前所述,拥塞窗口的大小定义了无需等待确认即可发送的最大比特数。发送方需要等待一个完整的往返过程才能获得确认。因此,通过将拥塞窗口的大小除以往返时间,我们可以得到最大的理论带宽:
Bandwidth=WinSize/RTT
这个简单的等式表明带宽是延迟的函数。TCP会非常努力地优化窗口大小,因为它对往返时间无能为力。但这并不总能得到最优的配置。
总而言之,拥塞控制是一种自适应机制,用于推断网络的底层带宽和拥塞。在应用程序级别也可以应用类似的模式。想象一下你在Netflix上看电影时会发生什么。它开始模糊的;然后,它稳定到一个合理的水平,直到出现一个小问题,质量再次恶化。这种应用于视频流的机制称为自适应比特率流。
记住这个
如果您正在使用HTTP,那么您将受到底层协议的支配。如果你不知道底层怎么工作,你就不可能得到最好的性能。
突发请求会受到冷启动的惩罚。使用TCP和TLS握手发送第一个字节可能需要多次往返。由于拥塞控制的工作方式,往返时间越短,底层网络的带宽利用率就越高。
关于这个主题已经有很多书了,你可以做很多事情来充分利用每一分带宽。但是如果你必须记住一件关于TCP的事情,那就让它这样吧: 您不能以超过光速的速度发送数据,但您可以做的是将服务器放在离客户端更近的位置,并重用连接,以避免冷启动带来的不利影响。