网络Midbox处理TCP的方式对TCP吞吐的影响

2023-10-27 15:50

本文主要是介绍网络Midbox处理TCP的方式对TCP吞吐的影响,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

昨天下班的路上,我发了一则朋友圈:

今天抓到一条大鱼,隧道的TCP载荷吞吐提升一倍多,哈哈,周末愉快!
很多隧道都用同一个线程处理同一个tcp流,这显然不对,应该用不同的线程分别处理一个流的两个方向。

但很多用户态隧道都是同一个线程处理同一条tcp连接的,这是问题。

这个问题在很多人看来真的很low,依然是那种不过如此的问题,因为怕被笑话,我故意把事情说的很low,但这只是一种措辞处理的技巧,本来这事儿就这么过去了。

但深入思考是我的习惯,我发现这竟然是一个普遍的问题,就准备记录下来。

这不是一个和性能有关的多处理优化问题,这只是一个非常简单的保持全双工的问题!

如果一个midbox无法保持全双工处理,那么它便破坏了互联网的基本原则。

当一条TCP流经过一个隧道的时候,它的trace波形图是下面的样子:
在这里插入图片描述
而正常的trace图应该是下面的:
在这里插入图片描述
关于TCP是如何均匀填满整个BDP管道的动力学我就不分析了,之前说过太多。只是看到上述的 阶梯状 trace图之后,你会怎么做?

我先说我会怎么做。

很明显,首先,我不会去查什么中间链路上的隧道之类的,看到如此明显的 空窗期 ,见招拆招 填充它 便是了。于是:
在这里插入图片描述
调试TCP CC绝对是一个类似拆弹的手艺活儿,但往往也能体现一个人的技术素质,比如我就不合格:

  • 我不去分析造成这种阶梯波形的原因,反而一上来就见招拆招地填补空窗期…

如此填窗是很简单的,一个stap -g脚本就能搞定。然而填窗之后,trace波形惨不忍睹…大量丢包,一片红,队形全乱!
在这里插入图片描述

嗯,我就是没有坐诊直接开颅的那个庸医华佗!

好了,现在收起生锈的手术刀,开始分析根因。同时比对一下接收端的trace波形就能发现端倪:
在这里插入图片描述

TCP平滑的trace波形是背靠背的数据和ACK形成的,ACK提供反馈,促发数据的发送:
在这里插入图片描述
平滑的trace图意味着什么?

平滑的trace图意味着 每一个数据段之间的间隔相同或者大致相同! 这要求:

  • 每一个ACK之间的间隔相同或者大致相同(不考虑延迟ACK或者完全考虑延迟ACK)。

平滑的ACK流促发平滑的数据流!

简而言之, 网络必须“同时”处理数据段和ACK段! 只有这样数据段和ACK段之间才不会因为互斥而引入延迟,我们知道,任意持续引入的延迟都会逐渐放大,让trace波形变成阶梯。

如果网络中间有一个midbox,它只能每次处理一个报文,那么会怎样?
在这里插入图片描述

本来背靠背的流量被midbox整形成了带有gap的,那么trace波形图显然也就从一条斜线变成阶梯状了。

仅仅变成阶梯状吗?它实际的后果是什么?我们观察阶梯状的trace图,发送方向的那个空窗期其实是midbox在处理另一个方向的ACK,显而易见,时间被两个方向共享了,吞吐即下降一倍。

当分离两个方向的处理后,正如预期的,吞吐翻倍。

好的,现在的结论很明确了,就是midbox的锅!但是midbox到底是什么?midbox具有什么特征才会造成阶梯状的trace波形呢?

如果midbox是一个单进程单线程的服务,必须OpenVXY,那必然结果如此。但如果midbox是一个多进程多线程的服务,相比之下是不是会避开这个坑呢?

也未必。当说到这个midbox多处理话题的时候,很多人会想当然认为直接打散就好了,要么按流打散,要么按包打散,但都有坑:

  • 按流打散,会造成本文所描述的现象,一个流被同一个线程处理,但一个线程同时只能处理一个方向啊!
  • 按包打散,会造成单流乱序的增加,如果SACK超过了发送端对乱序度的忍耐程度,便会增加重传降低有效带宽。

实际上还有一个维度,即 按方向打散 ,然后在每个方向上再按流打散。我们有一个现成的实例,就是这么做的,那就是Linux内核协议栈:

  • 网卡可以按包元组hash做RSS(这显然是区分方向的),然后Linux内核协议栈确保在同一个CPU Core上完成从接收到转发的流程。

说来很挺简单, 网络是什么样子的,midbox不要破坏它便是了。显然,网络是全双工的,midbox也要设计成全双工的,而要实现全双工,至少需要两个线程,一个方向一个,不是吗?

这里的道理显然很简单,与并发,多核编程模型毫无关系,与hash也没关系,这里只是一个保持全双工的问题。

还有一个buffer bloat的问题。

单线程处理一个流的半双工midbox实际上促使了数据段和ACK段的排队,如果一个方向上过来的包不能马上被处理,当然要排队了。正如我们想象的,很多midbox其实都可以被戏称为排队buffer,所以pacing队形在经过了几跳之后很难再被保持,这也是为什么BBR很多情况下不符合预期的原因之一。

总之,我对运营商的大多数转发设备是不信任的,我不觉得它们能保持你的pacing rate( 如果它们不是因为没有这个义务而不做,那就是它们没有这个能力 ),即便这个pacing rate低于它们的限速值,它们也能给你整成burst。纯正的BBR行为还是要内网观测,放到运营商公网,纯正的队形就像坎尼会战中的罗马军团,刹那间被冲散!


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

这篇关于网络Midbox处理TCP的方式对TCP吞吐的影响的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/286707

相关文章

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

springboot security之前后端分离配置方式

《springbootsecurity之前后端分离配置方式》:本文主要介绍springbootsecurity之前后端分离配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的... 目录前言自定义配置认证失败自定义处理登录相关接口匿名访问前置文章总结前言spring boot secu

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties