TCP的Window Size和Scale参数对传输效率的影响

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据同步 1个月
简介: 目前大多数互联网数据通信都是通过TCP协议进行的,了解其通信方式对提高通信效率,排查通信效率问题有很重要的意义。一. TCP的滑动窗口机制1. 概述TCP协议是可靠的通信协议,数据发送方发送给数据接收方的每一个包必须需要数据接收方返回对应的ACK,否则数据发送方就需要重传这个包。这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。如果你说完一句话,我在处理其他事情,没有

目前大多数互联网数据通信都是通过TCP协议进行的,了解其通信方式对提高通信效率,排查通信效率问题有很重要的意义。

一. TCP的滑动窗口机制

1. 概述

TCP协议是可靠的通信协议,数据发送方发送给数据接收方的每一个包必须需要数据接收方返回对应的ACK,否则数据发送方就需要重传这个包。这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。

为解决这个问题,TCP 引入了滑动窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」。如下图:

图中的 ACK 600 确认应答报文丢失,也没关系,因为可以通过下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就意味着 700 之前的所有数据「接收方」都收到了。这个模式就叫累计确认或者累计应答。

2. 流量控制

数据发送方发送数据和处理ACK的方式需要一个机制来保证数据传输的可靠性的同时确保数据发送方发送速度和数据接收方的处理数据速度保持一致,避免数据接收方处理不了了,数据发送方还在持续发送,也就是说需要这个机制来做流量控制。

TCP协议使用滑动窗口方式来实现流量控制。首先明确滑动窗口的范畴:TCP是双工的协议,会话的双方都可以同时接收和发送数据。TCP会话的双方都各自维护一个发送窗口和一个接收窗口。各自的接收窗口大小取决于应用、系统、硬件的限制(TCP传输速率不能大于应用的数据处理速率)。各自的发送窗口需要和对端进行协商来决定窗口的大小的。

3. 窗口大小的协商

TCP 头里有一个字段叫 Window,也就是窗口大小。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

3.1 参数说明:

建立连接:

  • Flag中的Window size value:窗口的大小
  • Flag中的Calculated Window size:放大后窗口的大小,也就是实际可用的大小
  • Options中的Window scale:窗口可以放大的倍数,也就是Calculated Window size最大等于Window size value 乘以 2 的 Window scale 次方

比如Window size value如果等于1024,Window scale等于7,那么Calculated Window size最大可以等于1024*128=131072

传输过程中,可以在抓包的数据中看到Win字段的大小就是目前TCP接收方可用窗口的大小。

3.2 建立连接时告知对方自己接收窗口大小

发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。TCP是双工通信的,TCP连接在建立时,双方互相告知自己接收窗口的大小,避免对方发送的数据大于自己接收窗口的尺寸。下面是一个实例:

A机器发SYN包中告诉对端自己接收窗口大小为7300并且不可放大:

B机器回的ACK包告诉A机器自己接收窗口大小为28960,并且可以扩大128倍:

在这个示例中,B机器向A机器发送数据的时候,因为A机器的窗口比较小且不可扩展,可能会因为窗口过小导致传输效率过低的问题。

3.3 通信过程中协商窗口大小

在数据传输过程中数据接收方会根据自身缓存的处理速度和余量来和发送方协商窗口大小,下面抓包是一个较好的通讯过程中协商窗口大小的例子:

  1. 包175,接收方发送ACK携带WIN = 384,告知发送方,现在只能接收384个字节
  2. 包176,发送方果真只发送了384个字节,Wireshark也比较智能,也宣告TCP Window Full
  3. 包177,接收方回复一个ACK,并通告窗口为0,说明接收方已经收到所有数据,并保存到缓冲区,但是这个时候应用程序并没有接收这些数据,导致缓冲区没有更多的空间,故通告窗口为0, 这也就是所谓的零窗口,零窗口期间,发送方停止发送数据
  4. 发送方察觉到窗口为0,则不再发送数据给接收方
  5. 包178,接收方发送一个窗口通告,告知发送方已经有接收数据的能力了,可以发送数据包了
  6. 包179,接收方收到窗口通告之后,就发送缓冲区内的数据了.

4. 窗口滑动

4.1 发送方窗口滑动

发送方的发送数据如下图所示被分为四类:

1.已经成功发送,并且收到确认

2.已经发送成功尚未确认

3.未发送,准备发送

4.未发送,不允许发送

其中第二类数据和第三类数据处于TCP发送端的滑动窗口中,发送窗口只有收到发送窗口内字节的ACK确认,才会移动发送窗口的左边界;

发送方只能发送第三类数据,如果窗口很小,那么每一批发送的数据也就很少,如果ACK返回很慢,那么数据传输速度会非常慢

4.2 接收方窗口滑动

接收方的缓存数据分为三类:

1. 已接收并已确认

2. 未接受但准备好接收(接收窗口)

3. 尚未接收并尚未准备好接收

接收方窗口只有在前面所有的段都确认的情况下才会移动左边界。当在前面还有字节未接收但收到后面字节的情况下,窗口不会移动,并不对后续字节确认。以此确保发送方会对这些数据重传。

三. Window Scale过小对传输速率的影响

TCP传输数据时,发送方窗口过小或者接收方窗口过小,都会严重影响数据传输的效率,特别在异地跨机房传输数据的情形,由于ACK返回的时间较长,窗口过小对数据传输速率的影响会被放大。

下面我们来做一个实验来验证发送方窗口过小会严重影响TCP传输速率,实验的前置条件是:

  1. 异地机房,一个包从发送方发送给接收方时间开销15ms左右;
  2. 发送方TCP窗口大小为8092字节,不可扩张;

我们来看下传输过程的截图:

从这个截图我们可以看到发送方每一批数据分四个包发,四个包的总尺寸加起来正好是8092个字节,包发送出去后等30毫秒后才收到ACK,然后开始发送下一批8092个字节的数据。也就是说每发送8KB的数据需要30MS左右,按照这个速度发送10Mbit(1028KB)的数据大约,1028/8*30/1000=4.8秒,这个速度比较慢了。

我们做个调优,将发送方的窗口设置为64KB,并且设置Window scale为7,再来传输大文件,下面是抓包截图:

由于发送方的窗口足够大,发送请求的时候不需要等待ACK,可以持续在连接上写TCP数据包,在发送方看来,发送33KB才花费0.6MS,加上路上的时间,发送10Mb的数据一共花费了880MS,还不到一秒,效率提升了5倍多。

四.JAVA的apache httpclient设置发送和接收窗口大小

Java的apache httpclient是使用较广的HTTP连接池开源库,在使用的时候允许用户设置rcvBufSize和sndBufSize,如果设置了这两个值,也就设置了TCP连接中本端的发送方和接收方窗口的大小,最要命的是代码设置了之后就关闭了linux内核的动态调整功能,会严重影响通信效率,建议不设置,由linux系统根据自身资源来动态调整TCP连接的发送方和接收方窗口的大小。

五.总结

本文科普了TCP连接中窗口滑动机制的原理,详述了窗口大小动态调整的机制,在第三节详细描述了发送窗口过小可能导致数据传输过慢的根本原因:

发送方在发送完窗口内的数据后,需要等待ACK回来后才能继续发送下一批数据,在窗口很小的时候,发送方大部分时间都在等待ACK,所以会严重影响传输速率,特别在发送方和接收方距离较远RT较高时更加明显。

通过程序设置rcvBufSize和sndBufSize会导致窗口不可动态变化,建议在通常情况下不要设置,除非有特别的考虑。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
弹性计算 网络协议 算法
记一次典型的TCP传输吞吐效率问题
客户在ECS上实现了一个供小图片上传的接口,通过高防->SLB->ECS的网络链路将接口发布给终端用户,但是发现上传的速率很不理想。初看起来像是高防问题,但是通过排查最终发现这是一个典型的TCP传输吞吐量问题,并且是由于后端服务器端的配置而引起,在此记录下排查过程和相关原理。
记一次典型的TCP传输吞吐效率问题
|
缓存 网络协议 算法
四十一、TCP可靠传输、流量控制、拥塞控制
四十一、TCP可靠传输、流量控制、拥塞控制
四十一、TCP可靠传输、流量控制、拥塞控制
|
缓存 网络协议 算法
计算机网络学习26:TCP/UDP对比区别、TCP流量控制、拥塞控制、超时重传时间的选择、可靠传输的实现
UDP: User Datagram Protocol 用户数据报协议 TCP: Transmission Control Protocol 传输控制协议 同时这里指的连接是指逻辑连接,而不是物理连接。
计算机网络学习26:TCP/UDP对比区别、TCP流量控制、拥塞控制、超时重传时间的选择、可靠传输的实现
|
存储 网络协议 算法
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)(下)
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)(下)
|
网络协议 安全 机器人
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)(上)
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)
《我要进大厂》- 计算机网络夺命连环20问,你能坚持到第几问?(应用层协议 | TCP三次握手、四次挥手 | TCP可靠传输 | Cookie&Session)(上)
|
缓存 网络协议 安全
CentOS7下使用TCP over TLS方式安全传输远程主机系统日志
CentOS7下使用TCP over TLS方式安全传输远程主机系统日志
354 0
CentOS7下使用TCP over TLS方式安全传输远程主机系统日志
|
网络协议
TCP/UDP相关-三次握手四次挥手以及为什么三次握手-如何实现可靠UDP传输
TCP/UDP相关-三次握手四次挥手以及为什么三次握手-如何实现可靠UDP传输
148 0
|
缓存 网络协议 算法
TCP 学习笔记(三) 可靠传输
TCP 学习笔记(三) 可靠传输
TCP 学习笔记(三) 可靠传输
|
存储 缓存 网络协议
面试官:换人!他连 TCP 这几个参数都不懂
TCP 三次握手的性能提升; TCP 四次挥手的性能提升; TCP 数据传输的性能提升;
面试官:换人!他连 TCP 这几个参数都不懂
|
网络协议 Java
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )
262 0
【Java 网络编程】TCP 传输机制 ( 数据拆分 | 排序 | 顺序发送 | 顺序组装 | 超时重发 )