资讯详情

TCP Delayed ACK 辩证考

TCP Delayed ACK 的 WiKi 解释: 在这里插入图片描述 看看红框中提到的一些性能下降的场景: 是不是很复杂?尤其是跟踪? Nagle 算法,混淆窗口综合征揉在一起,需要了解各种情况如何组合这些配置。

复杂的根源在哪里?

先看 Delayed ACK 目标:减少 Pure ACK 数量,提升有效载荷率。

再看 Nagle 算法目标:减少小包数量,提高有效载荷率。

为什么两者目标一致?

根源在于 Delayed ACK 在接收端,Nagle 算法在发送端,不知道对端情况。两端对齐,只靠猜测肯定不行。

TCP 在 1981 年被 RFC793 标准化,Delayed ACK 在 1989 年 RFC1122 中发布,Nagle 算法在 1984年 RFC896中发布,RFC793 定义的 TCP 头没有任何 Delayed ACK 和 Nagle 表达算法的能力,且 RFC1122 和 RFC896 未对 TCP 任何修改头部。

找到根源,就会有解决方案,两种配置由发送端统一决定。 TCP 扩大头部,提高其清晰的表达能力:

在这 6 bits 在保留空间内找一个 bit,其意义是:

  • b0:是否立即回应对端决定,并保持兼容性。
  • b1.对端必须立即响应。 对启用 Nagle 设置算法小包上的标志。协议可以在两端分别升级。如果其中一端不升级,则只会失去能力。

令人费解的是,为什么这么多年没有人做这个简单的扩展来提高协议的表达能力,而是制定了这么多原则:

  • 若服务端配置xxx,必须配置客户端xxx
  • 假如没有服务端xxx,必须使用客户端xxx

接着看 Delayed ACK 和 Nagle 算法的共同目标是提高网络的负载率。如果焦点集中在 Delayed ACK 和 Nagle 算法本身而不是它们的目标,很容易再次陷入复杂。

无论袋子有多小,如果设备和端主机消耗资源,。 Delayed ACK 和 Nagle 如果算法只是减少了网络数据包的数量,并卸载了转发设备的处理压力,那么 LRO/GRO 两者同时减少:

  • LRO/GRO 聚合 Data 接收端需要处理的数据包数量减少。
  • 聚合后的大块 Data 批量回应,减少 ACK 数量。

LRO/GRO 后的ACK 也可理解为 Delayed ACK,只是将 Delay 分批收集 Data 逻辑。我之前也做过实验验证,开启和未开启 LRO/GRO ,吞吐性能相差近两倍,根本原因是未打开 LRO/GRO 时过多的 Data 和 ACK 元数据处理费用的线性消耗。

一辆车运 100 千克,运 1 吨需要 10 辆车 10 司机,车运 1 吨,只需要 1 辆车 1 个司机。

LRO/GRO 成本是增加一点聚合延迟。

不管怎么聚合,一个 IP 包最大容量 64KB,Delayed ACK 也就能 skip 2*64KB 字节确认一回,但也仅此而已。最近的 BIG TCP patch 这个问题几乎是优化的: tcp: BIG TCP implementation

这些复杂的解决方案并没有从根本上解决问题,但优点是只有修改两端的一端才能有很好的效果。

如何从根本上解决问题需要改进 TCP 最大限度地的表达能力 Delayed ACK 收益。仍从 TCP 协议开始,这次借用 2 个 bits,当然了,这 2bits 也可以在 option 中实现:

  • b00:是否立即回应对端决定,保持兼容。
  • b01:对端必须立即响应。
  • b10:除非 RFC 如果要求必须立即响应,建议对方不要响应。
  • b11:N/A

统一决定发送端 ACK 不影响拥塞状态机的频率。

发送端可以在不影响采样的前提下做出以下决定,每个间隔 10*64KB 设置距离一次 b10 。这将使 Pure ACK 数量大大减少,达到 Data 和 ACK 的 640:1 为网络设备和端主机减轻数量比。

同样让我困惑的是,30年来没有人改变过 TCP 这些逻辑并不意味着升级不容易。 SACK,Timestamps,Fast Open 不都是后加的吗?考虑到兼容性,这些都是通过的 TCP option 协商决定。为什么? Delayed ACK 不呢?而且可以自然兼容,甚至不需要协商。

在我看来,数据包是否需要被使用? ACK 的标志位和 PSH 标志位没有什么不同。

遗憾但有趣的是,QUIC 竟然继承了 TCP 关于何时发送 ACK 该机制没有将该权力统一交给发送端。 QUIC 由于单机性能问题,设计中没有考虑单机性能问题 TCP 也没怎么想。

最新的 RFC9114 我还没有仔细看。这是我三年前做的一件事,典型的原因 QUIC 表达能力不足使事物复杂化,与单机性能有关。 case。

运行 QUIC 后 CPU 变高,发现 QUIC 的 Data/Pure ACK 数量比过高,ACK copy 用户态和上下文切换费用太大。TCP 那么多 ACK 单机性能问题不大,部分原因是 ACK 不需要copy 到用户态处理。

我想了一个主意,内核 GRO 这个位置捕捉相同 UDP 五元组,尽量将 UDP 考虑到报文聚集在一起 QUIC 是加密的,不方便内核解密,聚合 UDP Payload 用 TLV(Type-Length-Value) 分离后拼接,最后加一个 UDP 头统一上送,待一个大 UDP 收到用户态后,通过仓库层面 TLV 分成原始的 QUIC Payload,交给程序处理。

CPU 降了,可 Delivery rate 相对不准确,这显然是聚合 UDP 小包时额外延迟引入的误差。总的来说,我的折腾其实是 TCP LRO/GRO 那些在接收端做的事。

它似乎做了一件足够复杂和技术性的事情,但并没有从根本上解决问题。根本的解决办法是 QUIC 根据数据采集的需要和资源能力,发送端自行决定 Pure ACK 的频度。

有时候没有消息就是好消息,TCP 的 ACK 自时钟被认为是理所当然的,但实际上这只是一种手段。

考虑原始 TCP,接收端将是每一个 Data 包回送一个 ACK,若全世界的流量都是 TCP-Based,整个网络 50% 所有的数据包都是 ACK,50% 数量会计资源 ACK 因此,消耗减少 ACK 数量也在减轻整个互联网的负担。新的传输协议应该学得更好,不要比坏。

这就是我今天要讲的故事。

想想几年前做过的一个与单机性能有关的例子 case,结合 TCP Delayed ACK,写篇短文。

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

标签: jk9301b01振动变送器b00正反转速传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台