在没有多路径TCP的情况下进行多路径传输

2022-02-25 23:34:14

千兆以太网已经存在很长时间了,它无处不在,如果你的计算机上有一个RJ-45端口,它很有可能成为千兆以太网网络接口。

即使你看看已经超过20年历史的计算机,在它们的规格表上唯一突出的仍然是千兆以太网。

然而,如今,千兆以太网(1GBE)有时还不够。千兆住宅互联网接入变得越来越普遍,而这些消费者中的大多数都在使用WiFi,不太可能获得他们可能期望的千兆性能。有线连接可以轻松地最大限度地利用互联网和局域网链接。

万兆以太网(10GBE)正在缓慢地进入消费市场,值得注意的是,苹果产品已经使用万兆以太网有一段时间了,但使用万兆以太网交换机的人仍然很少。

我怀疑消费者以太网的速度在过去20年里没有提高的主要原因是,在大多数情况下,它已经足够快了。然而,像存储这样的东西现在已经显著加快了速度,不仅是更快的磁盘(平均SATA硬盘的运行速度约为2.5千兆位),而且闪存给了我们6千兆位的单驱动器速度,如果你看看NVMe(我的硬盘可以读取近20千兆位)。但当你看看我们可以发送给其他计算机的数据(想想像NAS这样的远程存储),我们很快就会受到1GBE的限制。

服务器是另一回事,但仍有相当多的服务器仍在1GBE、10GBE和25GBE(或更快)上运行用于带宽密集型的任何应用,因为当面临巨大的计算能力和存储容量时,网络可能很快成为主要瓶颈。

然而,单10GBE和25GBE链路并不总是您想要的。如果你想要更多的带宽呢?如果您连接的交换机需要软件升级或崩溃怎么办?出于这个原因,很多服务器的NIC都有两个物理端口,它们连接到同一个交换机(用于带宽增加)或不同的交换机(用于冗余/故障切换)。

但是系统如何利用多个以太网链路呢?他们对交换机和服务器进行编程,以使用链路聚合(LAG)。链路聚合意味着两条链路共享一个IP和MAC地址,并要求交换机和系统(至少在通常部署的802.3ad标准中)改变其行为。链接聚合按不同的名称命名,具体取决于配置它的供应商,名称包括:;聚合接口、NIC团队、端口通道和邦德。最后一个不时引起有趣的博客标题(A)

但是,链路聚合不会直接导致单个连接的性能提高。这是因为操作系统和网络层通常一次将一个连接指向一个以太网链路。因为TCP和其他进行拥塞控制的协议在呈现不一致的性能反馈时(因为不同的链路具有不同的容量和延迟)可能会变得混乱。虽然2x10GBE可能意味着您有20 GB的可用带宽,但由于连接定向/哈希逻辑,单个TCP连接只能以10 GB的速度运行。

在上一篇帖子中,我谈到了LTO磁带备份,以及驱动器本身如何比标准的千兆以太网链路进行读/写操作,如果通过网络将数据流传输到磁带,建议使用万兆网络,以避免出现问题。

不幸的是,在我的例子中,装有运行磁带机所需SAS卡的机器消耗了最后一个可能装有10GBE网卡的PCIe插槽。即使为承载磁带机的PC供电的系统是10GBE。这意味着我的磁带备份速度比需要的慢得多(并且在mbuffer上暂停)。

但我有USB 3.0端口,如果有USB 3端口,就可以选择使用USB千兆以太网加密狗。

然而,问题在于,虽然我本可以将主板和USB NIC设置为滞后状态,但这不会提高我的单个TCP连接(通过mbuffer)向磁带机馈电的速度。

我真的需要一种方法将两个NIC的吞吐量合并到一个2gbit/s流中。

多路径TCP(MPTCP)或RFC8684是一个扩展,允许单个TCP套接字跨越多个IP地址和网络接口。

该扩展目前很少使用,只有OpenMTCPRouter项目和苹果的Siri两种常用的部署用途

OpenMTCPRouter使用MPTCP来代理/隧道连接以获得更好的吞吐量,允许您将多个住宅连接链接到一个更快的代理服务器链接中,而Siri使用它来处理WiFi和蜂窝网络之间的快速故障切换,以确保在使用语音助手时获得最佳体验。

MPTCP在5.6版本中被合并到Linux内核中,但是我不知道有哪个主流发行版提供并启用了它。Ubuntu 20.10在其5.13内核上附带了MPTCP,而Debian Bullseye使用5.10,但禁用了MPTCP。

除了在操作系统中提供MPTCP支持之外。我发现MPTCP的可用性故事…不好?对某些事情说这样的话感觉真的很糟糕,但我自己对MPTCP的研究一直令人恼火。

这篇文章写于2022年2月24日,当你读到这篇文章时,情况可能已经改变了

由于MPTCP现在在主线Linux中发布,实际的项目网站本身似乎没有跟上进度,网站上的文档让我大吃一惊,结果发现写下的东西不再受支持,或者我只是没有找到任何方法来做他们记录的事情。老实说,我可能有点傻,但我发现最好的活文档是MPTCP的内核测试,因为根据定义,它们必须反映MPTCP的当前API。

我认为,总体而言,MPTCP带来的许多痛苦是,它被设计为自动检测并开始多路径通信,用户空间可以不必关心连接的细节。

正因为如此,我找不到一种方法从用户空间(忽略netlink等)中分辨出主机的多个端点,因此我放弃了编写mptcp客户机工具的尝试。

我对MPTCP不满意,我认为完全用户空间版本的这个概念是可能的,事实上,我当时正在和一个做合同工作的人有一个库,它似乎能够将多个连接“绑定”在一起。然而,在尝试让它工作时,我发现该库没有实现速度改进,故障切换行为最多也不可预测。

所以我努力确保它可以,对库进行全面检查,并对其进行修复。一旦它发挥了足够的作用,我就做出了可能破坏图书馆的决定。我自己做了叉子来控制行为的变化。

多路径go库实际上是一个相当复杂的机器。因为虽然MPTCP有原始数据包访问权,可以进行重试和子流排序,但多径却不行。它需要基本上是一个网络阵列。康涅狄格大学和他们的团队一起为带宽和弹性。这意味着任何符合网络的东西。go中的Conn是一个有序的可靠流(例如,WebSockets、TLS连接、某些模式下的SCTP等),可在该库中使用所有组合!

由于使用了类似TCP的套接字,性能永远不会像您自己使用UDP编写的那样好,但考虑到多路径库是以这种方式启动的,我决定即使在分叉之后也保持这种方式。

现在我已经有了图书馆,但我仍然需要一个工具来包装它,以供日常使用…

Bondcat的用户界面受到ncat的启发,但可以通过多个IP地址/端口组合连接到主机。这意味着,有了地址选择方面的一些知识(见下文),您可以轻松地跨平台突破单千兆以太网速度的限制。

我特别提到千兆以太网,因为就我所管理的而言,我并没有试图优化速度超过10千兆/秒的多路径库。这是因为在那个阶段,可能有更好的选择可以在非常快的滞后网络上移动大量数据,例如GridFTP。

但是,由于它的行为类似于netcat/ncat,因此您可以轻松地在其上包装连接,例如,您可以使用OpenSSH的proxy命令获得比千兆位SFTP/SCP更快的传输:

对于监听端,bondcat包括一个中继模式,它接受连接并将数据转发到另一个tcp端点。为了让这个ssh设置工作,我们可以将中继模式指向

如果这不是你的使用风格,你可以把它当作一个普通的netcat来发送信息:

现在需要为bondcat做一些考虑,因为MPTCP对您的网络堆栈有着比bondcat更好的了解(毕竟,发挥神奇作用的库只看到了一堆连接,仅此而已)。您需要小心选择用于用例的地址:

用例:通过互联网或试图摆脱滞后捆绑包的限制

这种用法很简单,只需像调用普通netcat(单地址)一样调用它,并使用-multiplier标志来表示要启动多少额外连接。如果要混合主机IPv4和IPv6地址,此标志也适用于其他地址。

我发现为局域网定位IPv6地址是最容易的。但这都是假设你所在的局域网有路由器广告。如果是这样的话,这是最好的选择。如果不是,则本地IPv4地址正常工作。

然而,这通常只适用于10GBE->;{n} x1GBE设置。默认情况下,Bondcat会尝试连接机器上的每个IP地址,以帮助自动提速。为了帮助这种“自动”工作,最好从接口最多的机器上启动连接。此功能可在-a或-no自动检测的情况下禁用

假设您所在的系统有两条链路,则需要手动添加一条路由,让其中一个端点通过备份链路。除此之外,它应该透明地工作。

我发现它对于将备份流式传输到磁带机非常有用,而且我相信库本身(分叉版本在同一代码repo中)将在bondcat之外找到用途。然而,我认为随着MPTCP得到更好的支持(如果幸运的话),该工具将慢慢过时。

如果你想了解博客的最新信息,可以使用RSS订阅源,也可以在Twitter上关注我

此外,我目前正在寻找三月份以后的工作。如果你喜欢我所做的,或者认为你可以利用我的一些奇怪的知识领域,请通过[email protected]!