TCP数据传输与性能

1、传输原理

TCP通过 “ 发送 — 应答 (ACK确认)”来确保传输的可靠性,它是端到端传输的。

        TCP传输是分段的,一个HTTP响应报文会被操作系统切成多个MSS(Maximum Segment Size)大小的段,直到接收端接受到完整的报文为止。在此过程中,报文分段按照顺序进行发送,每个报文段在发送时,会做顺序编号,以便能够完整正确地组装。

MSS:Maximum Segment Size 最大报文段长度,是TCP协议的一个选项,用于在TCP连接建立时,收发双方协商通信时每一个报文段所能承载的最大数据长度(不包括文段头)。如果MSS选项数据为512,则表示该报文段的发送方可以处理的最大报文段长度为512字节(不包括TCP与IP协议头长度)。主机一般默认MSS为536字节

端口号:

  • 表示同一个计算机上的不同进程
  • 源端口号和目标端口号都是占用了两个字节
  • TCP的源端口号和目标端口号预计IP报文中的源IP和目标IP确认一条唯一的TCP连接 

序号:4个字节

确认序号:ack,占四个字节

控制位:URG、ACK、PSH、RST、SYN、FIN

        TCP 的数据是通过名为 IP 分组( 或 IP 数据报) 的小数据块来发送的。HTTP就是“HTTP over TCP over IP” 这个“协议栈” 中的最顶层了。 其安全版本 HTTPS就是在 HTTP 和 TCP 之间插入了一个( 称为 TLS 或 SSL的) 密码加密层。

        HTTP 要传送一条报文时, 会以流的形式将报文数据的内容通过一条打开的TCP 连接按序传输。 TCP 收到数据流之后, 会将数据流砍成被称作段的小数据块, 并将段封装在 IP 分组中, 通过因特网进行传输。 所有这些工作都是由TCP/IP 软件来处理的, HTTP 程序员什么都看不到。

每个 TCP 段都是由 IP 分组承载, 从一个 IP 地址发送到另一个 IP 地址的。 每个 IP分组中都包括:

  • 一个 IP 分组首部(通常为 20 字节)
  • 一个 TCP 段首部(通常为 20 字节)
  • 一个 TCP 数据块(0 个或多个字节)

IP 首部包含源和目的 IP 地址、 长度和其他一些标记。 TCP 段的首部包含了TCP端口号、 TCP 控制标记, 以及用于数据排序和完整性检查的一些数字值。 

TCP 连接是通过 4 个值来识别的:
< 源 IP 地址、 源端口号、 目的 IP 地址、 目的端口号 > 

这 4 个值一起唯一地定义了一条连接。 两条不同的 TCP 连接不能在同一时刻拥有 4 个完全相同的地址组件值 

        有些连接共享了相同的目的端口号(C 和 D 都使用目的端口号 80)。 有些连接使用了相同的源 IP 地址(B 和 C)。 有些使用了相同的目的 IP 地址(A 和 B,C和 D)。 但没有两个不同连接所有的 4 个值都一样。 

2、滑动窗口协议

将TCP与UDP这样的简单传输协议区分开来的两种协议不同的传输数据的质量。
TCP对于发送数据进行跟踪,这种数据管理需要协议有以下两大关键功能:

可靠性:保证数据确实到达目的地。如果未到达,能够发现并重传。

数据流控:管理数据的发送速率,以使接收设备不致于过载。

要完成这些任务,整个协议操作是围绕滑动窗口确认机制来进行的。因此,理解了滑动窗口,也就是理解了TCP。

(1)在我们滑动窗口协议之前,我们如何来保证发送方与接收方之间,每个包都能被收到,并且是按次序的呢?

问题:吞吐量非常的低。我们发完包1,一定要等确认包1,我们才能发送第二个包。 

(2)那么我们就不能先连发几个包等他一起确认吗?这样的话速度更快,吞吐量更高

问题:如果过多的源同时以很快的速度发送大量的数据包,而此时接收方并没有如此高的接收数据的能力,因此极易导致网络的拥塞。 

(3)滑动窗口协议(Sliding Window Protocol)

        该协议是 TCP协议 的一种应用,用于网络数据传输时的流量控制,以避免拥塞的发生。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认。因此该协议可以加速数据的传输,提高网络吞吐量。滑动窗口算法其实和这个是一样的,只是用的地方场景不一样。

如果我们在任一时间点对于这一过程做一个“快照”,那么我们可以将TCP buffer中的数据分为以下四类,并把它们看作一个时间轴:

1. 已发送已确认 数据流中最早的字节已经发送并得到确认。这些数据是站在发送设备的角度来看的。

2. 已发送但尚未确认 已发送但尚未得到确认的字节。发送方在确认之前,不认为这些数据已经被处理。

3. 未发送而接收方已Ready 设备尚未将数据发出,但接收方根据最近一次关于发送方一次要发送多少字节确认自己有足够空间。发送方会立即尝试发送。

4. 未发送而接收方Not Ready 由于接收方not ready,还不允许将这部分数据发出。

说明:

  • 灰色1号2号3号包已经发送完毕,并且已经收到Ack。这些包就已经是过去式。
  • 4、5、6号包是黄色的,表示已经发送了。但是并没有收到对方的Ack,所以也不知道接收方有没有收到。
  • 7、8、9号包是淡蓝色的。是我们还没有发送的。这些淡蓝色也就是我们接下来马上要发送的包。
  • 后面的10-15还没有被读进内存。要等4号-9号包有接下来的动作后,我们的包才会继续往下发送。 

正常情况:

        可以看到4号包对方已经被接收到,所以被涂成了灰色。“窗口”就往右移一格。我们就把11号包读进了我们的缓存。进入了“待发送”的状态。8、9号包已经变成了黄色,表示已经发送出去了。接下来的操作就是一样的了,确认包后,窗口往后移继续将未发送的包读进缓存,把“待发送“状态的包变为”已发送“。 

丢包情况:

        有可能我们包(5-11)发过去,对方的Ack丢了。也有可能我们的包并没有发送过去。从发送方角度看就是我们没有收到Ack。

        发生的情况:一直在等Ack。如果一直等不到的话,我们也会把读进缓存的待发送的包也一起发过去。但是,这个时候我们的窗口已经发满了。所以并不能把12号包读进来,而是始终在等待5号包的Ack。 

问题:如果我们这个Ack始终不来怎么办呢?

超时重发/重传:

        原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。

        影响超时重传机制协议效率的一个关键参数是重传超时时间(RTO,Retransmission TimeOut)。RTO的值被设置过大过小都会对协议造成不利影响。

  • RTO设长了,重发就慢,没有效率,性能差。
  • RTO设短了,重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
  • 连接往返时间(RTT,Round Trip Time),指发送端从发送TCP包开始到接收它的立即响应所消耗的时间。

        在 Unix 以及 Windows 系统中,最初其重发超时的默认值一般设置为6秒(重发时间必须是0.5秒的倍数)左右。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。

        此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接,并且通知应用通信异常强行终止。

3、TCP性能

HTTP 紧挨着 TCP, 位于其上层, 所以 HTTP 事务的性能在很大程度上取决于底层TCP 通道的性能。

HTTP 事务的时延有以下几种主要原因。

(1) 通过 DNS 解析系统将 URI 中的主机名转换成一个 IP地址要花费对应的时间

(2) 每条新的 TCP 连接都会有连接建立时延,但如果有数百个 HTTP 事务的话, 这个时间消耗值会快速地叠加上去。

(3) 网络传输请求报文及服务器处理请求报文都需要时间。

(4) Web 服务器会回送 HTTP 响应的花费时间。 

        这些网络时延的大小取决于硬件速度、 网络和服务器的负载, 请求和响应报文的尺寸, 以及客户端和服务器之间的距离。 TCP 协议的技术复杂性也会对时延产生巨大的影响。

性能聚焦区域:

  • TCP 连接建立握手;
  • TCP 慢启动拥塞控制;
  • TCP 延迟确认算法;
  • Nagle 算法;

(1)TCP连接的握手时延

TCP 连接握手需要经过以下几个步骤。

  1. 请求新的 TCP 连接时, 客户端要向服务器发送一个小的 TCP 分组(通常是 40 ~60 个字节)。 这个分组中设置了一个特殊的 SYN 标记, 说明这是一个连接请求。 
  2. 如果服务器接受了连接, 就会对一些连接参数进行计算, 并向客户端回送一个TCP 分组, 这个分组中的 SYN 和 ACK 标记都被置位, 说明连接请求已被接受
  3. 客户端向服务器回送一条确认信息, 通知它连接已成功建立。现在的 TCP栈都允许客户端在这个确认分组中发送数据。

(2)延迟确认(ACK)

        由于网络自身无法确保可靠的分组传输( 如果网络设备超负荷的话, 可以随意丢弃分组), 所以 TCP 实现了自己的确认机制来确保数据的成功传输。每个 TCP 段都有一个序列号和数据完整性校验和。 服务端收到完好的TCP段时,都会向发送者回送小的确认报文。 如果发送者没有在指定的窗口时间内收到确认信息, 发送者就认为分组已损毁或丢失, 并重发数据。

        由于确认报文很小, 所以 TCP 允许在发往相同方向的输出数据分组中对其进行“捎带”。 TCP 将返回的确认信息与输出的数据分组结合在一起, 可以更有效地利用网络。 为了增加确认报文找到同向传输数据分组的可能性, 很多 TCP栈都实现了一种“延迟确认” 算法。 延迟确认算法会在一个特定的窗口时间( 通常是 100 ~ 200 毫秒) 内将输出确认存放在缓冲区中, 以寻找能够捎带它的输出数据分组。 如果在那个时间段内没有输出数据分组, 就将确认信息放在单独的分组中传送。

        但是当希望有相反方向回传分组的时候, 偏偏没有那么多。 通常, 延迟确认算法会引入相当大的时延。

(3)TCP慢启动

慢启动算法思路:

        主机开发发送数据报时,如果立即将大量的数据注入到网络中,可能会出现网络的拥塞。慢启动算法就是在主机刚开始发送数据报的时候先探测一下网络的状况,如果网络状况良好,发送方每发送一次文段都能正确的接受确认报文段。那么就从小到大的增加拥塞窗口的大小,即增加发送窗口的大小, 用于防止因特网的突然过载和拥塞。

        TCP 慢启动限制了一个 TCP 端点在任意时刻可以传输的分组数。 简单来说, 每成功接收一个分组, 发送端就有了发送另外两个分组的权限。 如果某个HTTP 事务有大量数据要发送, 是不能一次将所有分组都发送出去的。 必须发送一个分组, 等待确认; 然后可以发送两个分组, 每个分组都必须被确认,这样就可以发送四个分组了,以此类推。 这种方式被称为“打开拥塞窗口”。

(4)Nagle算法与TCP_NODELAY

        TCP/IP协议中,无论发送多少数据,总是要在数据前面加上协议头,同时,对方接收到数据,也需要发送ACK表示确认。为了尽可能的利用网络带宽,TCP总是希望尽可能的发送足够大的数据。(一个连接会设置MSS参数,因此,TCP/IP希望每次都能够以MSS尺寸的数据块来发送数据)。Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。如果 TCP 发送了大量包含少量数据的分组, 网络的性能就会严重下降。

Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

  • Nagle 算法鼓励发送全尺寸的数据段:Nagle 算法试图在发送一个分组之前, 将大量TCP 数据绑定在一起, 以提高网络效率。
  • 一个 TCP 连接上最多只能有一个未被确认的未完成的小分组,在该分组ACK 到达之前不能发送其他的小分组。如果其他分组仍然在传输过程中,就将那部分数据缓存起来。
  • 只有当挂起分组被确认, 或者缓存中积累了足够发送一个全尺寸分组的数据时, 才会将缓存的数据发送出去。

        Nagle 算法会引发几种 HTTP 性能问题。 首先, 小的 HTTP 报文可能无法填满一个分组, 可能会因为等待那些永远不会到来的额外数据而产生时延。 其次, Nagle 算法与延迟确认之间的交互存在问题——Nagle 算法会阻止数据的发送, 直到有确认分组抵达为止, 但确认分组自身会被延迟确认算法延迟 100~ 200 毫秒。

HTTP 应用程序常常会在自己的栈中设置参数 TCP_NODELAY, 禁用Nagle 算法,提高性能。(Tomcat通过server.xml进行设置,默认为true)注:TomCat服务默认是禁用了的

4、串行事务处理

        如果只对连接进行简单的管理, TCP 的性能时延可能会叠加起来。 比如, 假设有一 个包含了 3 个嵌入图片的 Web 页面。 浏览器需要发起 4 个 HTTP 事务来显示此页面:1 个用于顶层的 HTML 页面, 3 个用于嵌入的图片。 如果每个事务都需要(串行地建立) 一条新的连接, 那么连接时延和慢启动时延就会叠加起来 。

        除了串行加载引入的实际时延之外, 加载一幅图片时, 页面上其他地方都没有动静也会让人觉得速度很慢。 用户更希望能够同时加载多幅图片。 串行加载的另一个缺点是, 有些浏览器在对象加载完毕之前无法获知对象的尺寸,而且它们可能需要尺寸信息来决定将对象放在屏幕的什么位置上, 所以在加载了足够多的对象之前, 无法在屏幕上显示任何内容。 在这种情况下, 可能浏览器串行装载对象的进度很正常, 但用户面对的却是一个空白的屏幕, 对装载的进度一无所知。

还有几种现存和新兴的方法可以提高 HTTP 的连接性能:

并行连接:通过多条 TCP 连接发起并发的 HTTP 请求。

持久连接:重用 TCP 连接, 以消除连接及关闭时延。 

管道化连接:通过共享的 TCP 连接发起并发的 HTTP 请求。

5、并行连接

如前所述, 浏览器可以先完整地请求原始的 HTML 页面, 然后请求第一个嵌入对象, 然后请求第二个嵌入对象等, 以这种简单的方式对每个嵌入式对象进行串行处理。 但这样实在是太慢了!

HTTP 允许客户端(浏览器)打开多条TCP连接, 并行地执行多个 HTTP 事务(每个TCP连接处理一个HTTP事务)。 在这个例子中, 并行加载了四幅嵌入式图片, 每个事务都有自己的 TCP 连接。 页面上的每个组件都包含一个独立的HTTP 事务

并行连接不一定更快 : 

        打开大量连接会消耗很多内存资源, 从而引发自身的性能问题。 复杂的 Web页面可能会有数十或数百个内嵌对象。 客户端可能可以打开数百个连接, 但 Web服务器通常要同时处理很多其他用户的请求, 所以很少有 Web 服务器希望出现这样的情况。 一百个用户同时发出申请, 每个用户打开 100 个连接, 服务器就要负责处理10 000 个连接。 这会造成服务器性能的严重下降。 对高负荷的代理来说也同样如此。

实际上, 浏览器确实使用了并行连接, 但它们会将向同一个域名请求的并行连接的总数限制为一个较小的值。

浏览器同域名请求的最大并发数限制:

6、 持久连接

        Web 客户端经常会打开到同一个站点的连接。 比如, 一个 Web 页面上的大部分内嵌图片通常都来自同一个 Web 站点, 而且相当一部分指向其他对象的超链通常都指向同一个站点。 因此, 初始化了对某服务器 HTTP 请求的应用程序很可能会在不久的将来对那台服务器发起更多的请求(比如, 获取在线图片)。这种性质被称为站点局部性(site locality)。

        HTTP/1.1(以及 HTTP/1.0 的各种增强版本) 允许 HTTP 设备在事务处理结束之后将 TCP 连接保持在打开状态, 以便为未来的 HTTP 请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的 TCP 连接被称为持久连接。 非持久连接会在每个事务结束之后关闭。 持久连接会在不同事务之间保持打开状态,直到客户端或服务器决定将其关闭为止。

        重用已对目标服务器打开的空闲持久连接, 就可以避开缓慢的连接建立阶段。而且,已经打开的连接还可以避免慢启动的拥塞适应阶段, 以便更快速地进行数据的传输。

Connection: Keep-Alive

在持久连接中,每一个HTTP请求都是串行的。每个请求的发送都必须等待上一个请求的响应。 

7、管道化连接

HTTP/1.1 允许在持久连接上使用管道化(pipeline)技术。 这是相对于 keepalive连接的又一性能优化。

        在响应到达之前, 可以将多条请求放入队列。 当第一条请求通过网络流向另一端的服务器时, 第二条和第三条请求也可以开始发送了。 在高时延网络条件下, 这样做可以降低网络的环回时间, 提高性能。

对管道化连接有几条限制: 

  • 必须按照与请求相同的顺序回送 HTTP 响应(如果顺序发送了请求1/2/3,那么无论服务器处理哪个请求更快,相应的时候必须按照请求的顺序响应)。 HTTP 报文中没有序列号标签, 因此如果收到的响应失序了, 就没办法将其与请求匹配起来了。此时容易引起一个问题:头部阻塞。
  • HTTP 客户端必须做好连接会在任意时刻关闭的准备。 如果客户端打开了一条持久连接, 并立即发出了 10 条请求,服务器可能在只处理了5 条请求之后关闭连接,剩下的 5 条请求会失败,客户端必须能够应对这些过早关闭连接的情况, 重新发出这些请求。
  • 只有幂等的请求能够被管线化。HTTP 客户端不应该用管道化的方式发送会产生副作用的请求(比如 POST)。 由于无法安全地重试 POST 这样的非幂等请求, 所以出错时, 就存在某些方法永远不会被执行的风险。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悠然予夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值