Web 性能优化 - TCP

TCP 负责在不可靠的传输信道之上提供可靠的抽象层,向应用层隐藏了大多数网络通信的复杂性能,比如丢包重发、按需发送、拥塞控制及避免、数据完整,等等。采用 TCP 数据流可以确保发送的所有字节能够完整地被接收到,而且客户端的顺序也一样。

但是 TCP 设计并未过多顾及时间,由此给浏览器 Web 性能带来了挑战。

三次握手

所有 TCP 连接一开始都必须经过三次握手。客户端与服务器在交换应用数据之前,必须就起始分组序列号,以及其他一些连接相关的细节达成一致。处于安全考虑,序列号由两端随机生成。

image
  • SYN

    客户端选择一个随机序列号 x,并发送一个 SYN 分组,其中可能还包含 TCP 标志和选项。

  • SYN ACK

    服务器给 x 加 1,并选择自己的一个随机序列号 y,追加自己的标志和选项,然后返回响应。

  • ACK

    客户端给 x 和 y 加 1,并发送握手期间的最后一个 ACK 分组。

客户端可以在发送 ACK 分组之后立即发送数据,而服务器必须等接收到 ACK 分组之后发送数据。

每个 TCP 连接都要经过三次握手,倘若客户端与服务器距离过长,会造成非常大的性能影响。因而,提升 TCP 性能关键在于想办法重用连接。

为解决这个问题,人们在积极寻找各种方案,其中长链接(Keep-Alive)、负载均衡、TFO(tcp fast open)便是其中的一些解决办法。

长链接

Keep-Alive,HTTP 1.1 之后默认开启,指在一个 TCP 连接中可以持续发送多份数据而不会断开连接。

负载均衡

基本原理:客户端(如:ClientA)与负载均衡设备之间进行三次握手并发送 HTTP 请求。负载均衡设备收到请求后,会检测服务器是否存在空闲的长链接,如果不存在,服务器将建立一个新连接。当 HTTP 请求响应完成后,客户端与负载均衡设备协商关闭连接,而负载均衡则保持与服务器之间的这个连接。当有其他客户端(如:ClientB)需要发送 HTTP 请求时,负载均衡设备会直接向服务器之间保持的这个空闲连接发送 HTTP 请求,避免来由于新建 TCP 连接造成的延时和服务器资源耗费。

TCP 连接复用

TFO(tcp fast open)

尽管开启了长链接,可是依然有35%的请求是重新发起一条连接,而握手会造成一定的延迟,TFO 的目标就是为了去除这个延迟,在三次握手期间也能交换数据。

基本原理:

  • 客户端发送 SYN 包,包尾加一个 FOC 请求,只有4个字节。
  • 服务端收到 FOC 请求,验证后根据来源 ip 地址生成 Cookie(8个字节),将这个 cookie 加载到 SYN + ACK 包的末尾,发送至客户端。
  • 客户端缓存获取到的 Cookie 可以给下一次使用。
  • 下一次请求开始,客户端发送 SYN 包,这时候后面带上缓存的 Cookie,然后就开始正式发送数据。
  • 服务器验证 Cookie 正确,将数据交给上层应用处理得到相应结果,然后在发送 SYN + ACK,不再等待客户端的 ACK 确认,即开始发送相应数据。
TFO

网络拥塞

拥塞:即对供不应求,对资源的需求超过了可用的资源,网络性能下降,整个网络的吞吐量随之负荷的增大而减小,甚至会发生拥塞崩溃的现象。

为了减缓网络拥塞现象,TCP 加入许多机制用来控制双向发送数据的速度。如流量监控、拥塞控制、拥塞预防机制等。

流量控制

流量控制是一种预防发送端过多向接收端发送数据的机制。

滑动窗口是实现流量控制的一种方法,一个简单例子:

image

设 A 向 B 发送数据。在建立连接时,B 告诉了 A:“我的接收窗口值 rwnd = 400“ (rwnd: receiver window),因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值。TCP 窗口的单位时字节,并不是报文段。设每个报文段的字节长 100,而数据报文段序号的初始值为 1,大写 ACK 表示首部中的确认位 ACK,小写 ack 表示确认字段的值 ack。

从图中可以看出,B 进行了三次流量控制。第一次把窗口减少到 rwnd = 300,第二次又减少到了 rwnd = 100,最后减到 rwnd = 0,即不允许发送数据了。

当 rwnd = 0 时,则意味着必须由应用层先清空缓存区,才能接收剩余数据。这个过程贯穿于每个 TCP 连接的整个生命周期:每个 ACK 分组都会携带相应的最新的 rwnd 值,以便两端动态调整数据流,使之适应发送端和接收段的容量及处理能力。

慢启动

尽管流量监控可以防止发送端向接收端过多发送数据,但是发送端和接收端在连接建立之初,并不知道可用带宽是多少,因此需要一个估算机制,然后还可以根据网络中不断变化的条件而动态改变速度。

拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致于过载。

慢启动是实现拥塞控制的一种方法,此外还有拥塞预防、快速重发和快速恢复。

慢启动,即是在分组被确定以后,增大窗口大小,慢慢启动。

具体实现如下:

  • 发送方通过 TCP 连接初始化并维护一个拥塞窗口变量(cwnd)。并规定发送端与接收端之间最大可以传输的数据量为接收窗口(rwnd)与拥塞窗口(rwnd)的最小值。

cwnd 最初的值只有一个 TCP 段,1999年提升至 4 个 TCP 段,2013年,提升至 10 个 TCP 段。

  • 发送端向接受端发送 TCP 段后,停下来,等待确认。

  • 此后,每收到一个 ACK,慢启动算法都会告诉发送端,cwnd 窗口增加一个 TCP 段,并可以多发送两个新的分组。这个阶段称为指数增长阶段。

由于慢启动的设计,限制了可用的吞吐量。对于大型流式下载服务的影响倒不显著,但是对于小文件的传输却非常不利,常常会出现还没有达到最大窗口请求就被终止的情况。

简单演示三次握手与慢启动对简单 HTTP 传输的影响。

连接参数:

  • 往返事件:56ms。
  • 客户端到服务端带宽:5 Mbit/s。
  • 客户端和服务端接收窗口:65 535字节。
  • 初始的拥塞窗口:4 段(4 x 1460 字节 = 5.7 KB)。
  • 服务器生成响应的处理时间:40 ms。
  • 没有分组丢失,每个分组都要确认,GET 请求只占 1 段。
tcp 连接取得文件
  • 0 ms:客户端发送 SYN 分组开始 TCP 握手。
  • 28 ms:服务端响应 SYN - ACK 并指定其 rwnd 大小。
  • 56 ms:客户端确认 SYN - ACK,并指定其 rwnd 大小。并立即发送 HTTP GET 请求。
  • 84 ms:服务端接收到 HTTP 请求。
  • 124 ms:服务器生成 20 KB 的响应,并发送 4 个 TCP 段(假设初始 cwnd 为 4),然后等待 ACK。
  • 152 ms:客户端收到 4 个段,并分别发送 ACK 确认。
  • 180 ms:服务器针对每个 ACK 递增 cwnd,然后发送 8 个 TCP 段。
  • 208 ms:客户端接收到 8 个段,并分别发送 ACK 确认。
  • 236 ms:服务器针对每个 ACK 递增 cwnd,然后发送剩余 TCP 段。
  • 264 ms:客户端收到剩余的 TCP 段,并发送 ACK 确认。

当再次发送相同请求时:

再一次发送
  • 0 ms:客户端发送 HTTP 请求。
  • 28 ms:服务器收到 HTTP 请求。
  • 68 ms:服务器生成 20 KB 响应,此时 cwnd 已经大于发送文件所需的 15 段,因此可以一次性发送所有数据段。
  • 96 ms:客户端收到所有 15 个段,分别发送 ACK 确认。

拥塞预防

慢启用使用 cwnd 作为起始值发送数据量,随后成倍增长。直到超过接收系统配置的拥塞阈值(ssthresh)窗口,或者发生分组丢失现象,此时拥塞预防算法介入。

image

由于已经发生拥堵,必须采取删包措施。需要重新调整 cwnd 大小,此后拥塞预防按照自己的算法来增大 cwnd 以避免丢包。若再次丢包,则从头开始。

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 21.1 引言 TCP提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。T...
    张芳涛阅读 2,982评论 0 8
  • 24.1 引言 TCP已经在从1200 b/s的拨号SLIP链路到以太数据链路上运行了许多年。在80年代和90年代...
    张芳涛阅读 1,469评论 0 3
  • 传输层-TCP, TCP头部结构 ,TCP序列号和确认号详解 TCP主要解决下面的三个问题 1.数据的可靠传输...
    抓兔子的猫阅读 4,498评论 1 46
  • 1.这篇文章不是本人原创的,只是个人为了对这部分知识做一个整理和系统的输出而编辑成的,在此郑重地向本文所引用文章的...
    SOMCENT阅读 13,034评论 6 174
  • 个人认为,Goodboy1881先生的TCP /IP 协议详解学习博客系列博客是一部非常精彩的学习笔记,这虽然只是...
    贰零壹柒_fc10阅读 5,051评论 0 8