TCP传输基本原理简述及优化

吐槽君 分类:javascript

TCP传输基本原理简述及优化

目的是:对TCP优化知识进行了解

背景:TCP通过 “发送-应答(ACK确认)-重传机制” 来确保传输的可靠性,它是端到端进行传输的

存在的问题:传统的TCP底层实现,在很多时候会导致TCP传输效率变低,特别是网络带宽的扩充和整体网络硬件技术的提升,网络传输速度有很大的变化的现代。

TCP传输的简要说明

TCP传输是分段的,一个HTTP响应报文会被操作系统切成多个MSS(Maximum Segment Size,最大报文长度)大小(一般为1460 B,约 1.426kb)的段,发送端每次只会发送若干段。

能够发送多少个数据包,由拥塞窗口和接收端窗口共同决定,直到接收端接收到完整的报文为止。

  • 在此过程中,报文分段按照顺序进行发送,每个报文段在发送时,会做顺序编号,以便能够完整正确地组装

tcp很慢

当HTTP的请求响应模型将请求发送给服务器时,服务器响应都需要多个RTT(Round-Trip Time 往返时延)的传输,物理距离越远,总体网络耗时越长。

例如,如果大型网站的机房位于美国,用户在中国,而中美物理距离可能在10000km以上,那么用户端的一个数据包到达美国机房就需要30ms,加上中间路由设备的转发延迟,以及BGP各个运营商之间的绕路(会在“CDN 优化”一章中介绍),网络耗时150~200ms,有时甚至超过200ms。

每个报文发送多少段,就是由TCP的底层拥塞控制算法来进行控制的。报文越大,受拥塞控制算法的影响也越大,这也是本章可以重点优化的地方。

对于大型网站来说,一般有很多页面,这些页面经过HTTP的压缩之后,仍然会高达数十KB,甚至数百KB。而当远距离传输时,一个数据包的来回网络耗时少则数十毫秒,多则数百毫秒,优化空间更大

滑动窗口-接收端流量控制

滑动窗口本质上是描述接收方的TCP数据报缓冲区大小的数据的,发送方根据这个数据来计算自己最多能发送多长的数据。

  • 如果发送方收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0的数据报的到来。

可用于内网,局域网,可以限速

拥塞窗口-发送端流量控制

接收端流量控制在局域网内做流量控制是可行的,但是在公网上就会出现问题。

网络数据包在传输过程中,要经过很多路由器的转发,而这些路由器的带宽和缓冲区大小是不确定的。

  • 路由器的缓冲区太小,会造成数据包大量堆积甚至拥塞,而接收端的缓冲区一般很大,此时会造成大量的网络拥塞,从而加剧整个网络的拥塞,甚至造成整个互联网不可用。

为了解决这个问题,TCP发送方需要确认连接双方线路的数据最大QPS是多少,这就是所谓的拥塞窗口。

拥塞控制(慢启动算法):

目的:确定拥塞窗口(cwnd(congestion window))(最大传输速度QPS,比如 200kb/s)

TCP发送方首先发送一个(或者数个)数据报文段,然后等待对方的回应,ACK回应后就把这个窗口的大小加倍,然后连续发送两个数据报,对方回应以后,再把这个窗口加倍,这个机制就是发送端拥塞控制的慢启动算法

对慢启动算法的简单理解:

先发送少量的数据报文段,得到确认后,再将发送报文段的个数增加,直到出现超时错误或者丢包;

  • 发送端因此了解到网络的承载能力,也就确定了拥塞窗口的大小,发送方就根据这个拥塞窗口的大小发送数据。在下载文件时,一般开始比较慢,后面会慢慢变快,直到达到一个稳定的速度

举例: MSS(Maximum Segment Size,最大报文长度)大小约 1.4kb

  • 第一次发送 1.4kb, 第二次就翻倍,2.8kb, 第三次在翻倍5.6kb,一直翻倍,直到出现超时错误或者丢包。然后再以这个速度去传输,也就是 拥塞窗口的大小

公式:MSS x 2n (指数增长)

慢启动的过程如图

slow start.png

发现问题

比如第N次速度为100kb/s, 第N+1次速度为200kb/s,此时出现了超时错误或者丢包。则最大窗口会确定为100kb/s。

很明显是不合理的,因为最大速度很可能比 100kb/s 要大,这样会导致网络利用率不足

解决问题:拥塞避免

当发生超时没有得到对方的确认时,发送的报文段个数会线性增长(不像之前一样乘以2的指数增长了)

拥塞避免阶段 如图

slow start plus.png

传统TCP拥塞控制问题

  1. 慢启动会造成网络耗时变长,拥塞窗口默认较小,无论多大的带宽,默认初始值都为3。
  2. 当偶尔出现超时时,发送报文段的个数会出现指数退避,直接减半,在某些情况下会导致网络利用率不足。
  3. TCP建立连接需要三次握手,但是如果握手期间发生超时或者丢包,只能等待超时定时器溢出,一般需要3s,这会导致连接耗时过长。

优化总结

  1. 尽量将操作系统进行版本升级。
    • 高版本的Linux操作系统对TCP内核进行了多项优化,包括拥塞窗口变大、EarlyTransmit等算法优化。
  2. 尽量通过监控工具发现问题,例如LastMile。
    • 远距离的传输容易丢包,可以通过LastMile来发现问题。在建立连接的时候丢包,为了避免定时器溢出再进行报文的传输,可以通过调整初始RTO来减少网络耗时。
  3. 用户体验要注意 RTO。
    • RTO (Recovery Time Objective,复原时间目标)是企业可容许服务中断的时间长度
    • 服务器端耗时占用整体耗时的一小部分,要把主要精力放在网络耗时的减少上。如果是小型网站,服务的用户群相对比较集中,就不要考虑 TCP 优化,因为带来的收益往往很小。
  4. 尽量减小HTTP报文的大小。
    • 因为HTTP报文越小,传输所需要的RTT((Round-Trip Time 往返时延)次数越少,耗时越短,通常Ajax异步化是减少HTTP同步报文大小的主要手段。
  5. 尽量减少HTTP头的大小。
    • HTTP的Gzip压缩只针对HTTP主体,而HTTP头是不能被压缩的,要尽早对Cookie大小进行控制,因为Cookie往往是造成HTTP头偏大的主要因素,Cookie大小在很多时候都接近4KB的上限。
  6. 尽量将机房部署在离核心用户近的地方。
    • 通过减少网络距离来减少网络耗时。
  7. 尽量选择大的运营商。
    • 小的运营商往往在BGP选路时会绕路,造成网络耗时增加。

参考丛书《大型网站性能优化实战:从前端、网络、CDN到后端、大促的全链路性能优化详解》

回复

我来回复
  • 暂无回复内容