从一道面试题看 TCP 的吞吐极限
分享一个 TCP 面试题:单条 TCP 流如何打满香港到旧金山的 320Gbps 专线?(补充,写成 400Gbps 更具迷惑性,但预测大多数人都会跑偏,320Gbps 也就白给了)
这个题目是上周帮一个朋友想的,建议他别问三次握手,慢启动,快速重传,何时发 RST 了,来个情景分析吧。
如果候选人提到 TCP 序列号空间 4GB,香港到旧金山往返 200ms+,320Gbps 管道容量 8GB+,TCP 最大窗口受限,无法这个管道,至于后面说与不说,都算通过了。上来就 BBR 的,还得继续问三次握手。
下面是这个题目的解析。
先求一下 TCP 最大窗口。
在 32bit 的 unsigned int 圆环域上,两个数字顺时针间隔在一个半圆内才能无歧义比较大小(参考 Linux kernel 的 before,after 宏定义):
如上图的无歧义共识,TCP 窗口最大值被限制在 2^31 字节以内。
此外,根据 TCP 滑动窗口原理,sender 和 receiver 的窗口之间最大可相差一整窗:
因此,TCP 窗口的最终最大值为 2^31/2 = 2^30 字节。这是 TCP 窗口上限,即 1GB。200ms 链路,TCP 最多只能打满 1GB*8/0.2s = 160Gbps 的带宽。
如果允许稍微 patch TCP,如何填满 8GB 管道呢?这是个更有趣的问题。
Netflix 有个直接的方案,扩展序列号空间:64-bit Sequence Numbers for TCP
我这里重点说另一个 PAWS + Pacing 方案。
timestamp 是个天然升序标识,每 1ms 滴答一下,32bit timestamp 回绕一次要 49 天,值得使用。
320Gbps = 40GBps,大约 1ms 发出 40MB 数据,即每 100ms 发生序列号回绕。但只要控制 sender 的 pacing rate,每 1ms 送出 40MB 数据,就可将 rwnd 最大值扩至 2^31,不再受回绕限制:
道理很简单,1ms 粒度 pacing,相当于为 seq 增加了额外的顺序号,按 timestamp 编号每 40MB 数据,receiver 对 100 个 1ms 和 1ms 的 40MB 数据归并排序即可恢复 send 顺序:
注意,timestamp 指的是原始报文传输时的时间,即便发生重传,其timstamp 还是原始那个。
若发生丢包,由于 “since the sender and receiver windows can be out of phase by at most the window size【RFC1323-2.3】”,sender 和 receiver 之间最大 2^31 相差,在 2^32B 范围内,每个 seq 只出现一次,以 timestamp 做序号,自然不会有歧义。
大致算一下 2^31B 的窗口用 timestamp 做顺序号可以支撑多大的带宽。以 timestamp 的 1ms 精度,1ms 至少需要将 2^32 的两个半圆区分开,1ms 标识 2^31B 数据,即 16Tbps = 2TBps 的带宽。
进一步设想,若 timestamp 精度达到 us,所支撑的带宽将继续扩大,但系统开销也随之扩大,由于二者非线性关系,所以我不敢说 1000 倍。
以上是理论值计算,考虑到丢包,乱序,拥塞控制等因素,理论值几乎达不到,但它展示了一种可能性。
万变不离其中,我经常强调单调递增编码 packet,并设计新协议,但实际上 timestamp 就是一个天然编码标识,它确实编码了 “packet(每一个 segment 包含若干 byte)”,而非 Byte stream。
byte 大小固定没弹性,byte-based 滑动窗口没扩展性,带宽越大,传输字节越多,越快回绕。而 packet 不固定,它提供 1B ~ mss B 的弹性,且 mtu 可随底层传输技术发展而增加(如巨帧),显然 packet-based 滑动窗口可扩展性更佳。可见,2^32B = 4GB 的序列号空间直接参与传输和确认不适应长肥网络,不过在 byte/packet-based 滑动窗口争论正当时(参见:The design philosophy of the darpa internet protocols 第 10 节),管道既不长,更不肥,选择 byte-based 没毛病。
回到这个面试题,为什么不能上来就说 BBR,因为 cwnd limit 前,先碰到 rwnd limit,这才是硬伤,是壁垒。所以必须先解决 rwnd limit 问题,突破 rwnd 限制,至于 BBR,只是优化。
这个题目主要考察 3 个点,首先是对 TCP 协议头字段的理解,主要是 seq 和 wcale option,其次是对数字的敏感,比如东亚到加州湾区的时延,再次就是根本问题和次要问题的甄别能力,刚接触 BBR 的可能觉得 BBR 能解决一切问题,从而把根本问题疏忽了。
至于更多讨论,参见另一篇文章:流控问题两则。
现在来看可靠保序传输的本质。
要在 receiver 恢复 sender 端顺序,需顺序标识数据。将数据顺序装入 packet,然后顺序标识 packet 即可,但这个我已说过太多,现在看如何顺序标识数据本身。
TCP 序列号算一种顺序标识,但它会面临回绕歧义。TCP 将最大窗口限制在 2^30B 消除了歧义,但同时也限制了其填充长肥网络的能力。在引入 timestamp 后,可重新审视这个问题。
无论 seq space 多大,它终究被定义在环形域上(计算机算术一切数据类型都在环形域),环形域无歧义比较大小需在一个半圆内,当这个环形域不够大时,就会遇到 TCP 一样窗口限制,但若将这个环形域定义足够大,却可能占用额外报头空间,最好就是根据实际所需将环形域定义成变长(比如 QUIC)。但还有别的解法。
当我们发现时间序是一个天然顺序后,这个环形域便可分级解释,就像 MMU 分级页表一样。将顺序标识分为两层,外层是时间序,内层是环形域的半圆,设序列号空间 m 位,timestamp 精度为 n,只需要在 1 个 n 时间内能最大识别 2^(m-1)B 即可,也就是说,同一 timestamp 编码一个半圆。
m = 32,n = 1ms 就是 TCP 的情况,解释是,只要在 1ms 内发送数据不超过 2^31B 即可。2^31B 就是 2GB,对于 TCP,它可以支撑的带宽为 2TBps,与 RTT 无关。对于 receiver,执行两层归并排序,首先将时间分割为精度为 n 的 slot,根据 timestamp 将报文对应到 slot,再根据 seq 将报文在该 slot 内排序:
为什么 RTT 消失了?
RTT 并没消失,它回绕需要太久的时间,以至于可以将它近似为绝对单调递增量,前面算过,以 1ms 精度滴答的 timestamp 发生回绕需要 49 天,远超一个报文在互联网上最长逗留时间,当然,如果处在比地球大的多的星球,这一点需要修正。
这里有一个 packetization 过程,一个 slot 即一个 packetization 单位,内容是一个没有歧义的半圆内的 seq。
原始报文的 timestamp 时间序和 seq 字节序共同消除了保序歧义,另一面,为保证可靠传输,丢包重传还需要一个报文( whatever 原始报文 or 重传报文)实际发送的时间序列号,用来消除原始报文和重传报文的歧义,这个虽然不是流控必须的,但对拥塞控制意义重大,不得不察,但这方面我强调过太多,不再啰嗦。
现在可以和 Netflix 的方案(见上面链接)对应了,二者殊途同归,Netflix 方案直接采用了 64bit 序列号,而 PASW + Pacing 也使用 64bit 序列号,只是将它分为了 32bit 原始序列号和 32bit timestamp 两层。在我看来,PAWS + Pacing 更灵活,可以适配不同时钟精度和不同带宽。
所以,我有个建议,TCP 在同时启用 timestamp 和 wscale 时,wscale 需另作解释,将其最大值限制在 15 而不是 14,而 timestamp 也另解释为顺序号,为 2 倍的滑动窗口(即以 wscale 最大值 15 取代 RFC7323 规定的 14)消除回绕歧义。
从刚毕业参加工作面试一直到此后的 10 年多,被面试官问了无数次 TCP 三次握手,为什么三次,TimeWait,快速重传之类的问题,自己作为面试官也问了候选人无数次这般问题,我上一次被问这些是大约 5 年前,但也差不多从那时起我也不问候选人这些问题了,我想了一些更好玩的,比如 “如何用 TCP 实现不可靠传输(考察 ACK/SACK/滑动窗口)”,“如何旁路修改传输中的 TCP 数据(考察 RFC5961)?” … 正好有朋友也厌倦了上面那些老掉牙的问题,要我帮忙新出一个面试题,问题已经被问过,所以延迟一周写下本文。
浙江温州皮鞋湿,下雨进水不会胖。
相关文章:

从一道面试题看 TCP 的吞吐极限
分享一个 TCP 面试题:单条 TCP 流如何打满香港到旧金山的 320Gbps 专线?(补充,写成 400Gbps 更具迷惑性,但预测大多数人都会跑偏,320Gbps 也就白给了) 这个题目是上周帮一个朋友想的,建议他别问三次握手&a…...
rsync 的用法
rsync 介绍下 用法 rsync是一个常用的数据同步工具,它能够在本地和远程系统之间同步文件和目录。以下是rsync的基本用法: 同步本地文件夹: bash Copy code rsync -av /path/to/source /path/to/destination其中,-a表示归档模式&…...

【LeetCode每日一题:[面试题 17.05] 字母与数字-前缀和+Hash表】
题目描述 给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。 返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。 示例 1: 输入…...
华为OD机试题 - 简易压缩算法(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:简易压缩算法题目输入输出示例一输入输出说明示例二输入输出说明…...

Kubenates中的日志收集方案ELK(下)
1、rpm安装Logstash wget https://artifacts.elastic.co/downloads/logstash/logstash-6.8.7.rpm yum install -y logstash-6.8.7.rpm2、创建syslog配置 input {beats{port> 5044 } }output {elasticsearch {hosts > ["http://localhost:9200"]index …...

LeetCode - 42 接雨水
目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 42. 接雨水 - 力扣(LeetCode) 题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 示例1 输入&…...

python --生成时间序列,作为横轴的标签。时间跨越2008-2022年,生成每年的6-10月的第一天作为时间序列
python 生成制定的时间序列作为绘图时x轴的标签 问题需求 在绘图时,需要对于x轴的标签进行专门的设置,整体时间跨越2008年-2022年,将每年的6-10月的第一天生成一条时间序列,绘制成图。 解决思路 对于时间序列的生成࿰…...

【Unity VR开发】结合VRTK4.0:创建一个按钮(Togglr Button)
语录: 有人感激过你的善良吗,貌似他们只会得寸进尺。 前言: Toggle按钮是提供简单空间 UI 选项的另一种方式,在该选项中,按钮将保持其状态,直到再次单击它。这允许按钮处于激活状态或停用状态的情况&#…...

lottie-miniprogram在taro+vue的小程序中怎么使用
把一个json的动图展示在页面上。使用的是插件lottie-miniprogramhttps://blog.csdn.net/qq_33769914/article/details/128705922之前介绍过。但是发现使用在taro使用的时候他会报错。那可能是因为我们 wx.createSelectorQuery().select(#canvas).node(res > {console.log(re…...

C++回顾(二十二)—— stack容器 与 queue容器
22.1 stack容器 (1) stack容器简介 stack是堆栈容器,是一种“先进后出”的容器。stack是简单地装饰deque容器而成为另外的一种容器。添加头文件:#include <stack> (2)stack对象的默认构造 stack…...

逻辑优化基础-disjoint support decomposition
先遣兵 在了解 disjoint support decomposition 之前,先学习两个基本的概念。 disjoint 数学含义上的两个集合交集,所谓非相交,即交集为空集。 A∩BC⊘A \cap B C \oslash A∩BC⊘ support 逻辑综合中的 supportsupportsupport 概念是…...

保姆级使用PyTorch训练与评估自己的DaViT网络教程
文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址:https://github.com/Fafa-DL/Awesome-Backbones 操作教程:https://www.bilibili.co…...
Java8新特性:Stream流处理使用总结
一. 概述 Stream流是Java8推出的、批量处理数据集合的新特性,在java.util.stream包下。结合着Java8同期推出的另一项新技术:行为参数化(包括函数式接口、Lambda表达式、方法引用等),Java语言吸收了函数式编程的语法特…...
Java基准测试工具JMH高级使用
去年,我们写过一篇关于JMH的入门使用的文章:Java基准测试工具JMH使用,今天我们再来聊一下关于JMH的高阶使用。主要我们会围绕着以下几点来讲: 对称并发测试非对称并发测试阻塞并发测试Map并发测试 关键词 State 在很多时候我们…...

问心 | 再看token、session和cookie
什么是cookie HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。 什么是session Session 代表着服务器和客户端一次会话…...

Ubuntu 安装 CUDA and Cudnn
文章目录0 查看 nvidia驱动版本1 下载Cuda2 下载cudnn参考:0 查看 nvidia驱动版本 nvidia-smi1 下载Cuda 安装之前先安装 gcc g gdb 官方:https://developer.nvidia.com/cuda-toolkit-archive,与驱动版本进行对应,我这里是12.0…...

【漏洞复现】Grafana任意文件读取(CVE-2021-43798)
docker环境搭建 #进入环境 cd vulhub/grafana/CVE-2021-43798#启动环境,这个过程可能会有点慢,保持网络通畅 docker-compose up -d#查看环境 docker-compose ps直接访问虚拟机 IP地址:3000 目录遍历原理 目录遍历原理:攻击者可以通过将包含…...

磨金石教育摄影技能干货分享|春之旅拍
春天来一次短暂的旅行,你会选择哪里呢?春天的照片又该如何拍呢?看看下面的照片,或许能给你答案。照片的构图很巧妙,画面被分成两部分,一半湖泊,一半绿色树林。分开这些的是一条斜向的公路&#…...

中断以及 PIC可编程中断控制器
1 中断分为同步中断(中断)和异步中断(异常) 1.1 中断和异常的不同 中断由IO设备和定时器产生,用户的一次按键会引起中断。异步。 异常一般由程序错误产生或者由内核必须处理的异常条件产生。同步。缺页异常ÿ…...

SecureCRT 安装并绑定ENSP设备终端
软件下载链接链接:https://pan.baidu.com/s/1WFxmQgaO9bIiUTwBLSR4OA?pwd2023 提取码:2023 CRT安装:软件可以从上面链接进行下载,下载完成后解压如下:首先双击运行scrt-x64.8.5.4 软件,进行安装点击NEXT选…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...