7

browser networking - tcp

 3 years ago
source link: https://zhuanlan.zhihu.com/p/43349005
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

browser networking - tcp

人类的悲欢并不相通,我只觉得他们吵闹

近年来,WPO(Web Performance Optimization,Web性能优化)产业从无到有,快速增长,充分说明用户越来越重视访问速度方面的用户体验。

本篇文章主要介绍对所有网络通信都有决定性影响的两个方面:

  • 延迟

分组从信息源发送到目的地所需的时间

  • 带宽

逻辑或者物理通信路径的最大吞吐量

1. 延迟的组成

延迟是消息(Message)或分组(packet)从起点到终点经历的时间。

下面我们看一下,路由器这个负责转发消息的设备,会涉及哪些影响延迟的因素:

消息从发送端到接收端所需的时间,是信号传播距离和时间的函数

把消息中的所有比特转移到链路中需要的时间,是消息长度和链路速率的函数

处理分组首部,检查位错误以及确定分组目标所需要的时间

到来的分组排队等待处理的时间

缓冲区爆满(Bufferbloat)是Jim Gettys在2010年发明的一个术语,是排队延迟影响网络性能的一个形象说法。
造成这个问题的原因主要是:如今市面上的路由器都会配备很大的入站缓冲区,以便“不惜一切代价”避免丢包(分组)。可是,这种做法破坏了TCP的拥塞预防机制(congestion avoidance),导致网络中产生较长且可变的延迟时间。

搜索“Controlling Queue Delay”可了解详细内容。

2. TFO(TCP Fast Open)

举个例子,假设客户端在广州,服务器在北京,从广州发送分组到北京需要28ms。在此,连接的带宽对时间没有影响,延迟完全取决于客户端和服务端之间的往返时间。

建立一个三次握手至少需要花费56ms(客户端在发送握手期间最后一个Ack之后可以直接发送数据)。

三次握手的延迟使得每创建一个TCP连接都要付出很大代价,这也决定了提高TCP性能的关键,在于想办法重用TCP连接。(你是否对HTTP Header中的 keep-alive: true 还有印象?

事实上,由于非常短的TCP连接在互联网上随处可见,握手阶段已经成为影响网络总延迟的一个重要因素。为解决这个问题,人们在积极寻找各种方案,其中TFO(TCP Fast Open,TCP连接快速打开)就是这样一种机制,它致力于减少新建TCP连接的性能损失。

TCP快速打开(英语:TCP Fast Open,简称TFO)是对计算机网络中传输控制协议(TCP)连接的一种简化握手手续的拓展,用于提高两端点间连接的打开速度。
它通过握手开始时的SYN包中的TFO cookie(一个TCP选项)来验证一个之前连接过的客户端。如果验证成功,它可以在三次握手最终的ACK包收到之前就开始发送数据,这样便跳过了一个绕路的行为,更在传输开始时就降低了延迟。这个加密的Cookie被存储在客户端,在一开始的连接时被设定好。然后每当客户端连接时,这个Cookie被重复返回。

3. 拥塞控制 - Nagle's algorithm

1984年初,John Nagle提出了一种被称为“拥塞崩溃”的现象,这个现象会节点间带宽量不对称的任何网络。

由于往返时间超过了所有主机的最大终端间隔,于是相应的主机会在网络中制造越来越多的数据副本,使得整个网络陷入瘫痪。最终,所有交换节点的缓冲区都将被填满,多出来的分组必须删掉。目前的分组往返时间已经被设置为最大值,主机会把每个分组都发送好几次,结果每个分组的某个副本会到达目标,这就是拥塞崩溃。

这种情况永远存在,达到饱和状态时,只要选择被删除的分组算法合适,网络就可以退而求其次的继续生存下去。
- John Nagle

为了解决这些问题,TCP加入了很多问题,以便控制双向发送数据的速度,比如流量控制,拥塞控制,拥塞预防机制。

流量控制是一种预防发送端过多向接收端发送数据的机制。否则,接收端可能因为忙碌,负载重或缓冲区既定而无法处理。为实现流量控制,TCP连接的每一方都要通告自己的接收窗口(rwnd),其中包含能保存数据的缓冲区大小的空间。

4. 慢启动 - TCP Slow Start

尽管TCP有了流量控制机制,但网络拥塞崩溃仍然在1980年代中后期浮出水面。流量控制确实可以预防发送端向接收端过多发送数据,但却没有机制预防任何一端向潜在的网络过多发送数据。换句话说,发送端和接收端在建立连接之初,谁也不知道可用带宽是多少,因此需要一个估算机制,然后还要根据网络中不断变化的条件动态改变速度。

要理慢启动,最好看一个例子:假设广州有一个客户端,想要从北京的服务器上取得一个文件。首先,三次握手,而且在此期间又通过ACK分组通告自己的接收窗口大小(rwnd)。

此时,根据交换所得的rwnd是估算客户端和服务端可用带宽的唯一办法,而且这也是慢启动算法的设计思路。首先,服务器通过TCP连接初始化一个新的拥塞窗口(cwnd)变量,将其值设置为一个系统的保守值(在Linux中就是initcwnd)。

发送端和接收端不会同步这个值(cwnd),而且网络状况在不断变化。那么客户端和服务器端怎么确定拥塞窗口大小的最优值呢?解决方案就是慢启动,即在分组被确认后增加窗口大小。

cwnd达到N所需要的时间:

为什么知道慢启动对我们构建浏览器应用如此重要呢?因为包括HTTP在内的很多应用都运行在TCP之上,无论带宽多大,每个TCP连接都必须经过慢启动阶段。换句话说,我们不可能一上来就完全利用网络的最大带宽!相反,我们从一个相对较小的拥塞窗口开始,每次往返都令其翻倍(指数式增长)。

5. 拥塞预防

TCP调节性能主要依赖丢包反馈机制。慢启动以保守的方式初始化连接,随后的每次往返都会成倍提高传输的数据量,直到超过接收端的流量控制窗口,即系统配置的拥塞阈值(ssthresh)窗口,直至有分组丢失为止,此时拥塞预防算法介入。

拥塞预防算法把丢包作为网络拥塞的标志,即路径中某个连接或路由器已经拥堵了,以至于必须采取删包措施。因此,必须调节窗口大小,避免造成更多的包丢失,从而保证网络畅通。

重置拥塞窗口后,拥塞预防机制按照自己的算法来增大窗口以避免丢包,某个时刻可能又会有包丢失,于是这个过程又重新开始。

6. 队首阻塞 - Head of Line Blocking

TCP在不可靠的信道上提供了可靠的网络传输。基本的分组错误检测与纠正、按序交付、丢包重传以及保证网络高效率的流量控制,拥塞控制。

虽然TCP很流行,但它并不是唯一的选择,甚至在某些情况下不是最佳的选择。比如说“按序交付”:每个TCP分组都是带着一个唯一的序列号出发,而所有分组必须按顺序到达接收端。如果中途有一个分组没能到达接收端,那么后续分组必须保存在接收端的TCP缓冲区里,等待丢失的分组重发并到达接收端。

这种效应称为TCP的队首(HOL Head of Line)阻塞

7. 应用程序调优

  • 把服务器内核升级到最新版本(Linux:3.2+)
  • 确保cwnd大小为10
  • 禁用空闲之后的慢启动
  • 确保启动窗口缩放
  • 减少传输冗余数据
  • 压缩要传输的数据
  • 把服务器放在离用户近的地方减少往返时间
  • 尽最大可能重用已经建立的TCP连接

参考链接:

Networking 101: Building Blocks of TCP - High Performance Browser Networking (O'Reilly)​hpbn.co


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK