TCP 流控问题两则

两个基础的问题,可作为面试题目:

  1. TCP window scale 最大是多少?为什么?
  2. TCP单流有吞吐上限吗?如果有,是什么?如果没有,为什么?

第一个问题,如果回答 14 ,那一定是对标志很熟悉了,rfc1323 TCP WINDOW SCALE OPTION 小节有专门讲。

为什么是 14 ?

要识别一个序号相对另一个序号在前还是在后,窗口必须不能大于半个 2^32 字节,最大值为 2^31 字节,也就是 2 GB,理由见下图:
TCP 流控问题两则_第1张图片
b 和 b‘ 分别和 a 的关系是什么,before,or after ?

拿一个半圆的弧,一个端点放在 a :

  • 如果 b 在以 a 为起点顺时针的半圆弧内,那么 before(a, b) 为真。
  • 如果 b 在以 a 为起点逆时针的半圆弧内,那么 after(a,b) 为真。

考虑到发送端和接收端的时序同步,最大窗口取 2^30 字节。

TCP 窗口字段 16bits ,即 2^16,解方程 2^16 * 2^x = 2^30,x 即为 14。这是第一题答案。
TCP 流控问题两则_第2张图片
第二题呢?有坑。

如果答出第一题,第二题很容易陷进坑里。

既然窗口最大限制为 2^30,推论 BDP 最大 1 GB,以 100Gbps 链路为例解释。

100 Gbps = 12.5 GBps,1 GB 的 BDP,能支撑的最大 RTT 为 1 GB / 12.5 GBps = 0.08 s = 80 ms。即 80 ms 的 RTT 是 100Gbps 网卡的传输上限。

由此推论,以链路带宽和 RTT 计算,TCP 窗口存在固定上限意味着任何连接都存在一个传输上限。
果真如此吗?

问题出在 “最大窗口 1 GB 意味着 DBP 为 1 GB”。没有任何指标限制 “最大窗口就是最大 BDP”。至少理论上没有这个限制。

还是老问题,若应用程序接收足够快,接收速率大于等于发送端网卡速率的话,TCP 可应对任何带宽。

再次重申,TCP 传输带宽不应受窗口限制,窗口是一个数量,而带宽是一个携带时间因子的速率,如果接收足够快且 ACK 反馈足够及时,即便 1 字节的窗口也能打满任意大带宽。

1 字节窗口窗口能打满带宽?是不是不易理解?TCP 传输加速不是一直在追求大窗口吗?

事实上,TCP 慢的原因不是窗口不够大,而是 ACK 不够快。

拥塞控制最直接手段就是数据包守恒,ACK 一个字节发送一个字节,ACK 足够快意味着发送足够快,在这个基底外,探测空闲带宽反而是额外操作。

可惜 TCP 一开始就一直在控制数量而不是控制速率。这导致无论从端到端流控还是拥塞控制,均在控制数量:

  • 流控不考虑应用读取速率,造成 rwnd 成为限制。
  • 拥塞控制不考虑链路带宽,造成 cwnd 成为限制。

BBR 一定程度上改变了这种认知,但流控方面的 Rate-based 实现还没有任何改变,不过我倒是实现了一个简版,思路在下面的文章里:
新 TCP 流控

再快的网卡也是一个bit一个bit发的,不是吗?窗口不是限制。

所以第二题的答案是,TCP单流有吞吐没有上限。

照这么说,完全基于速率做流控的话,Window Scale 这个 option 本身都是不必要的。

当然,理想是一回事,现实是另一回事,Linux TCP 并不是按照上述理想实现的,以后可能也不会改变,Linux TCP 代码已成屎山,经不起 Rate-based 流控改造了。

昨天下午跟友上专门搞 TCP 加速的讨论问题,抽象了两个问题,总结一下。

浙江温州皮鞋湿,下雨进水不会胖。

你可能感兴趣的:(tcp/ip,网络,服务器)