网络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

相关文章

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON:

Debian系和Redhat系防火墙配置方式

《Debian系和Redhat系防火墙配置方式》文章对比了Debian系UFW和Redhat系Firewalld防火墙的安装、启用禁用、端口管理、规则查看及注意事项,强调SSH端口需开放、规则持久化,... 目录Debian系UFW防火墙1. 安装2. 启用与禁用3. 基本命令4. 注意事项5. 示例配置R

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Python获取浏览器Cookies的四种方式小结

《Python获取浏览器Cookies的四种方式小结》在进行Web应用程序测试和开发时,获取浏览器Cookies是一项重要任务,本文我们介绍四种用Python获取浏览器Cookies的方式,具有一定的... 目录什么是 Cookie?1.使用Selenium库获取浏览器Cookies2.使用浏览器开发者工具

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取