设计资源共享
资源共享:统计复用
互联网上的链路和交换机容量是有限的。我们需要解决的一个关键设计问题是:如何在不同的互联网用户之间共享这些资源?
让我们把这个问题更形式化一点。回想一下,流是两个终端主机之间交换的数据包流(例如,你和朋友之间的视频通话)。尽管容量有限,互联网需要同时支持许多并发流。

我们常说网络资源是统计复用的,这意味着我们会根据用户的需求动态地为用户分配资源,而不是为用户划分固定份额的资源。

打个比方,想想你的个人电脑。你的电脑并不会预先将一半的 CPU 分配给 Firefox,另一半分配给 Zoom,也不会只允许每个应用使用其分配到的那一半 CPU。相反,你的电脑会根据不同应用的需求动态分配资源。
统计复用如今在计算机科学中无处不在。例如,在云计算中,不同的公司可能会在数据中心动态共享资源。
统计复用是高效共享网络资源的好方法,因为用户需求会随时间变化。你可能不会每秒、每天 24 小时都使用恒定的 10 Mbps 带宽。你醒着的时候需求可能更高,睡着的时候需求更低。
使统计复用有效的前提是:实际上,总需求的峰值远小于各峰值需求的总和。
让我们来详细解释一下。假设有两个用户 A 和 B。我们可以绘制出每个用户随时间变化的需求。

我们需要分配多少容量才能完全满足两个用户的需求呢?
不好的策略(无统计复用)是计算各峰值需求的总和。我们找到 A 的峰值需求和 B 的峰值需求,然后把它们加起来。

如果我们分配这么多容量,肯定能满足他们的需求。A 的峰值需求是 X,所以我们给 A 分配 X,同样,给 B 分配 Y。然而,这种方法很浪费,因为 A 的峰值和 B 的峰值并不是同时出现的。

更好的策略(统计复用)是先通过绘制他们的总需求随时间变化的图表来计算总需求。例如,新图表中上午 10 点的需求是 A 在上午 10 点的需求加上 B 在上午 10 点的需求。然后,我们计算总需求的峰值。

如果我们分配这么多容量,就不能再静态地给每个用户分配一部分了。但是,通过随时间动态改变分配给每个用户的容量,我们仍然可以成功满足他们的需求,即使容量更小。

统计复用方法允许我们用更少的容量支持相同的用户(对我们来说更便宜,资源利用更高效)。对于许多分布情况,我们可以证明总需求的峰值实际上更接近平均需求的总和,这远小于各峰值需求的总和。
实际上,在网络中,我们不会为所有事情同时达到峰值的绝对最坏情况做准备。相反,我们动态地共享资源,并希望峰值不会同时出现。峰值仍然可能同时出现,这会导致数据包延迟或丢弃(回想一下链路队列)。尽管如此,我们做出了统计复用的设计选择,以更高效地利用资源,同时承担相应的后果(偶尔的同时峰值)。
归根结底,统计复用是一种有取舍的设计选择,不同的用户可能会做出不同的选择。例如,金融交易所有时会决定建立自己的专用网络来支持峰值需求,因为他们更关心在高峰时段确保网络连接,而且他们有能力承担额外的成本。
资源共享:电路交换与分组交换
现在我们知道可以使用统计复用來决定要构建多少容量。接下来的问题是:我们实际上如何在用户之间动态分配资源?
打个比方,想想一家受欢迎的餐厅,有很多顾客,但桌子数量有限。我们可以想到两种为顾客分配桌子的方式:可以让顾客预订,也可以先到先得。
网络中共享资源的两种方法与此类似。一种方法是尽力而为。每个人都把数据发送到网络中,不做任何预订,只能希望一切顺利。不能保证有足够的带宽来满足你的需求。
尽力而为的典型设计称为分组交换。交换机独立地查看每个数据包,并将数据包转发到更接近其目的地的地方。交换机不考虑流或预订。
除了数据包彼此独立之外,交换机之间也是独立的。当一个数据包在交换机之间跳转时,每个交换机都独立地处理该数据包(交换机之间不进行协调)。

另一种方法基于预订。在流开始时,用户明确请求并预订他们需要的带宽。数据发送完毕后,资源可以释放供其他人预订。
在研究和行业中都有探索的预订的典型设计称为电路交换。
在流开始时,终端主机通过某种路由算法确定一条穿过网络的路径(交换机和链路的序列)。(我们还没有讨论用于找到这条路径的路由算法,所以现在你可以假设它是通过某种 “魔法” 实现的。)
然后,源端向目的端发送一个特殊的预订请求消息。沿途的每个交换机也会收到这个请求。如果每个交换机都接受该请求,那么预订就完成了,源端和目的端之间就建立了一个由交换机组成的电路。

一旦每个交换机都确认了预订,就可以发送数据了。最终,当流结束时,源端向接收端发送一个拆除消息。沿途的每个交换机都会看到这个消息,并释放其容量。

注意:我们这里使用 “电路” 这个术语,是因为这个想法来自电话网络,电话网络使用相同的想法让两个人能够通话。
请记住,电路交换和分组交换都体现了统计复用。主要区别在于我们分配资源的粒度:基于预订的按流分配,或基于尽力而为的按包分配。即使在电路交换中,我们也是根据预订动态分配资源。我们不会预先为可能存在的所有流进行预订。

电路交换与分组交换的权衡
现在我们有两种在互联网上共享资源的方法。哪种更好呢?这取决于我们用来评估每种方法的标准。
我们可以从四个维度来比较这两种方法。
- 这对网络向应用开发者提供的抽象(或 API)来说是否是个好选择?
电路交换为开发者提供了更有用的抽象,因为它有预订带宽的保证。这给了开发者更可预测和更易理解的行为(假设一切顺利)。打个比方,想想在云中预订一台机器来运行某个任务。如果开发者知道他们将要使用的机器的规格,就更容易推理性能。如果开发者不知道他们使用的是哪台机器,任务仍然可以运行,但性能就不那么可预测了。
如果你是一位需要向用户分配资源的网络运营商,电路交换也是一种有用的抽象。你确切地知道每个用户请求多少带宽,并且可以向他们收取相应的费用。如果不能保证向客户提供的服务,就很难实现直观的商业模式。
- 这种方法在规模上是否高效?这种方法是否利用了网络上所有可用的带宽,还是有一些带宽被浪费了?
分组交换通常效率更高。具体好多少取决于流量源的突发性。
如果每个发送者在所有时间都以恒定速率发送数据,那么电路交换和分组交换都能充分利用容量。

相比之下,如果每个发送者的速率随时间变化,那么分组交换能让我们更好地利用带宽。

这是一个需求随时间变化的例子。有了预订,三个流必须预订 12、11 和 13 Mbps。其中一个预订会被拒绝,因为我们只能分配 30 Mbps。
这种方法在两个方面浪费带宽。预订 12 Mbps 的流在大部分时间里实际上并没有使用其带宽。此外,如果 12 Mbps 和 11 Mbps 的流获得了预订,我们还有 7 Mbps 未被任何人预订。
相比之下,在分组交换方法中,我们只是在数据包到达时发送它们,任何时候使用的总带宽都不会超过 30 Mbps。我们可以用现有的带宽支持所有流。
形式上,流的突发性定义为其峰值速率与平均速率之比。对于什么是平滑的或突发的,没有明确的阈值(它们更多是描述性术语)。
语音通话的比率通常比较平滑,比如 3:1,而网页浏览的比率通常更突发,比如 100:1。(语音通话的比率平滑也是电话网络使用预订的原因!)
分组交换更高效的另一个原因是:电路交换在建立和拆除电路时会花费额外的时间。这对于非常短的流(例如,下载一个小文件)来说尤其低效。
- 每种方法在规模上处理故障的能力如何?
分组交换在规模上处理故障的能力更好。如果一个路由器发生故障,我们可以沿着网络中的另一条路径发送数据包。(我们还没有讨论如何做到这一点,但事实证明路由算法很擅长适应故障。)终端主机不需要做任何不同的事情。
相比之下,在电路交换中,如果路径上的一个路由器发生故障,网络仍然需要找到一条新的路径,但终端主机需要做更多的事情。主机必须以某种方式检测到故障,并且必须重新发送预订请求。它还必须以某种方式释放旧路径上的预订。如果新的预订请求被拒绝了怎么办?
这种故障模式的扩展性很差。如果一个路由器出现故障,但有数百万个流在使用该路由器,那么就必须同时重新建立数百万个预订请求。
我们不会详细解决这些问题,但希望你能感觉到在电路交换中处理故障是一个相当困难的问题。
- 每种方法在规模上实现的复杂度如何?
如果你真的尝试设计电路交换,很多额外的设计问题会很快让协议变得非常复杂。
路由器如何知道预订成功了?当 2 看到请求并同意时,它如何知道 3 和 4 也同意了?(可能的方法:我们向相反的方向发送一个确认,表明预订已确认。)
如果预订请求在途中丢失了怎么办?1 和 2 同意了,但请求数据包在到达 3 和 4 之前被丢弃了。(可能的方法:设置一个计时器,如果在规定时间内没有确认预订,就删除该预订。现在终端主机必须重试。)
如果请求被发送且所有人都同意了,但返回的确认被丢弃了怎么办?4 和 3 看到了确认,但确认数据包在到达 2 和 1 之前被丢弃了。
如果预订被拒绝了怎么办?终端主机应该重试并请求更少的带宽吗?终端主机应该等待一会儿,然后用相同的请求再试一次吗?路由器应该在拒绝中说 “我不能提供 10 Mbps,但我可以给你 8 Mbps 吗?”
我们不会解决所有的设计问题,但希望你注意到电路交换的实现比最初看起来要困难。
使电路交换变得复杂的根本问题是状态共识。所有路由器都必须跟踪额外的状态,并且它们都必须就该状态达成一致。
你可能听说过 Paxos 协议,它们是让多个处理器就状态达成一致的极其复杂的协议。实际上,人们会在 4-5 台服务器组成的组上运行这些算法。在电路交换中,我们基本上是要求互联网在互联网规模上运行这种协议,涉及数百万个路由器和流。
总结一下:电路交换为应用程序提供了更好的性能,有预订的带宽。它也给了开发者更可预测的行为。
然而,分组交换使我们能更高效地共享带宽,并且没有启动时间。它还使我们能更容易地从故障中恢复,并且通常实现起来更简单(路由器需要考虑的事情更少)。
实际中的电路交换与分组交换
在现代互联网中,分组交换是默认方法。
电路交换的使用案例有限。例如,RSVP(资源预留协议)可以在小型局域网中使用,允许路由器(不是终端主机)在彼此之间预留带宽。
现代互联网中电路交换的另一个用途是专用电路(例如,MPLS 电路、租用线路)。作为一家公司,你可以专门购买一些互联网带宽(可能包括物理基础设施)供你的业务专用。这比标准的互联网连接要昂贵得多。
专用电路的部署规模不如假设的全互联网电路交换那么宏大。通常由人工设置预订。预订是长期的(例如,数年)。预订的粒度是公司,而不是单个流。
简史:当互联网在 20 世纪 70-80 年代首次被设计为一个规模较小的、由政府资助的研究项目时,它是分组交换的。
20 世纪 90 年代,当政府停止资助互联网并将控制权移交给商业企业时,研究界和行业认为我们需要转向电路交换。设计者预测语音和直播电视将是互联网的主要高负载用途。这两种应用都有平滑的带宽需求,适合电路交换。此外,由于互联网服务提供商必须从商业化的新互联网中赚钱,他们认为电路交换将提供更直观的商业模式。
研究界和标准机构做了大量工作来实现电路交换,但最终,这是一个失败的愿景,原因我们已经讨论过很多。此外,推动互联网增长的主要应用是电子邮件和网页,而不是语音通话和电视,这也是电路交换愿景未能实现的另一个原因。
这些设计选择的一个有趣结果是,用户和开发者适应了分组交换的现实。如果你在观看视频时网络连接不好,你已经习惯了应用程序会做出调整,视频质量会下降。(对比广播电视,它不会这样做。)这是一个关于技术如何改变用户行为的教训!
(注:文档部分内容可能由 AI 生成)