40、性能问题(传输层)

引言

  • 在计算机网络中,性能问题非常重要。当成百上千台计算机相互连接在一起时,无法预知结果的复杂交互过程很常见。这种复杂性常常会导致很差的性能,而且无人知道其中的缘由。在下面的章节中,我们将讨论许多与网络性能有关的问题,以便了解可能存在哪些问题以及如何处理这些问题。
  • 不幸的是,理解网络性能更像是一门艺术,而不是一门科学。这里很少有可在实践中应用的基础理论。我们能够做的最好方法是给出一些来自于实践的经验规则,并且展示一些真实世界中的例子。我们有意将这部分讨论推迟到学习了TCP 的传输层之后,因为应用程序获得的性能依赖于传输层、网络层和链路层的结合,而且能够在不同场合中使用TCP作为例子。
  • 在下面的章节中,我们将考查网络性能的如下6 个方面。
    Cl )性能问题。
    (2 )网络性能的测量。
    (3 )快速网络中的主机设计。
    (4 )快速处理段。
    (5 )头的压缩。
    (6 )“长肥”网路的协议。
    上述这些方面同时从主机和网络,以及网络速度和规模增长来考虑网络性能。

1、计算机网络中的性能问题

  • 有些性能问题(比如拥塞)是由于临时资源过载所引起的。如果到达一台路由器的流量突然超过了它的处理能力,那么,拥塞就会发生,从而导致性能问题。当网络中存在结构性的资源不平衡时,性能也会退化。例如,如果将一条千兆位的通信线路连接到一台低档的PC 上,则性能较差的CPU 将无法快速地处理入境数据包,因此有些数据包将会被丢失。这些数据包最终会被重传,既增加了延迟,又浪费了带宽,而且往往降低了性能。
  • 过载也可能被同步触发。例如,如果一个段包含了一个坏参数(比如,它的目标端口),那么,在许多情形下,接收端会尽职地返回一个错误通知。现在请考虑,如果将一个坏段广播给1000 台机器将发生什么样的情况:每台机器都可能送回一个错误消息。由此引发的广播风暴( broadcast storm )可能会严重地削弱网络的性能。以前, UDP 协议就遭受过这个问题,直到ICMP 协议作了修改,使主机不再对发送给广播地址的UDP 段中错误做出响应,以免遭受广播风暴。对于无线网络来说,由于广播本质上会发生,而且无线带宽有限,因此尤其要小心避免未经检查的广播响应。同步触发过载的另一个例子是掉电之后发生的情形。当电源恢复时,所有的机器同时启动系统。一个典型的启动序列可能如下:首先与某一台(DHCP )服务器联系,以便获得一个真实的身份:然后与某一台文件服务器联系,以便获得操作系统的一份副本。如果一个数据中心的成千上万台机器同时做这些事情,则服务器可能因不堪重负而崩溃。即使不存在同步过载,并且资源也足够,同样也可能由于缺少系统总体协调而发生性能退化的现象。例如,如果一台机器有足够的CPU 能力和内存,但是并没有为缓冲区空间分配足够多的内存,则流量控制机制将放缓段的接收,从而限制了传输性能。当Internet 变得越来越快,而流量控制窗口仍然维持在64 KB大小时,许多TCP 连接都存在这个问题。
  • 另一个调整问题是超时间隔的设置。当一个段被发送出去时, TCP 通常会设置一个计时器来预防该段的丢失。如果超时间隔设置得太短,将会发生不必要的重传,从而堵塞线路:如果超时间隔设置得太长,当段被丢失之后将导致不必要的延迟。其他可以调整的参数包括捎带确认应该等待数据段多长时间之后未果才发送单独的确认以及应该尝试经过多少次重传之后再放弃。
  • 对于诸如音频和视频的实时应用,它们的另一个性能问题是抖动。仅仅有足够的平均带宽还不足以有良好的性能。这些应用还要求较小的传输延迟。要想同时获得较短的延迟必须小心规划网络中的流量负载,同时还需要链路层和网络层共同支持服务质量。

2、网络性能测量

  • 当一个网络的运行效果很差时,它的用户通常会向网络运营商抱怨并要求提高网络质量。为了改善网络性能,网络操作人员首先必须弄清楚发生了什么问题。为了找出真正的问题所在,操作人员需要对网络进行测量。在本小节中,我们来考查网络性能的测量问题。下面的许多讨论以( Mogul, 1993 )的工作为基础。
  • 测量工作可以有许多不同的方式,也可以在不同的地点进行(既指物理位置,也指协议战中的位置)。最基本的一种测量手段是在开始某一个动作时启动一个计时器,然后确定该动作需要多长时间。例如,知道一个段需要多长时间才能被确认是很关键的一个测量指标。其他一些测量指标可以通过计数器来完成,即记录某种事件发生的次数(比如丢失的段数量)。最后,人们通常对于某些事物的数量比较感兴趣,比如在特定的时间间隔内所处理的字节数。
  • 测量网络的性能和参数有许多潜在的陷阱。以下我们列出其中一部分。任何一种系统化的网络性能测量手段都应该小心地避免这些陷阱。

确保样值空间足够大

  • 不要仅仅测量发送一个段的时间,而是要重复地测量,比如说测量100 万次,然后再取平均值。启动效应可能放慢第一个段的速度,而且排队会引入变化,比如802.16 NIC 或者线缆调制解调器在一个空闲周期后获得带宽预留。采用大量的样本可以减小测量均值和标准方差中的不确定性。这种不确定性可以利用标准的统计公式计算出来。

确保样值具有代表性

  • 理想情况下,这一百万次测量的完整序列应该分布在一天或者一周的不同时刻重复进行,以此来看不同的网络条件对测量数值的影响。例如,对于拥塞的测量,如果仅仅在没有拥塞的那一刻来测量网络拥塞,那么这样的测量以及结果没什么用。有时候测量结果初看起来可能不符合直觉,比如在上午11 点和下午1 点钟网络严重拥塞,但是中午时候却没有拥塞(所有的用户都去吃午饭了〉。
  • 在无线网络中,信号的传播位置是一个很重要的变量。由于天线的差异,即使测量节点放置在靠近无线客户端也可能无法观察到与客户端相同的数据包。在研究中最好从无线客户端进行测量,考查它究竟看到了什么。如果做不到这一点,那就使用技术把从不同角度的无线测量结合起来以便对正在发生的事情有个更全面的了解( Mahajan 等, 2006 )。

缓存可以破坏测量结果

  • 如果协议使用了缓存机制,那么重复多次测量将返回一个不可预测的快速答复。例如,获取一个Web 页面或者查询一个DNS 名字(来发现其IP 地址〉可能只有第一次涉及网络交换,以后返回的都是从缓冲区获得的结果,没有真正往网络上发送任何数据包。这样的测量结果本质上是没有什么价值的(除非你要测量的就是缓冲性能〉。
  • 缓冲机制也有类似的影响。己经有TCP/IP 性能测试报告称UDP 可以获得比网络允许的要好得多的性能。这是怎么发生的呢?调用UDP 时一旦内核接受了消息并且消息被排入传输队列之后,通常控制权就马上返回给应用程序了。如果主机上有足够的缓冲空间,则执行1000 次UDP 调用也不意味着所有的数据都己经被发送出去。大多数数据包仍然在内核中,但是性能测试程序却认为它们都己经被传送出去了。建议测试时,你要绝对确保网络操作是如何缓存以及缓冲数据的。

确保测试期间不会发生不可知事情

  • 测量时如果有人在你的网络上运行一个视频会议,那么通常得到的测量结果和没有视频会议时的测量结果不同。最好在一个空闲的网络上进行测试,并且根据需要自己创建所需的工作负载。不过这种做法也存在缺陷。尽管你认为在凌晨3 点钟时不会有人使用网络,但有可能自动备份程序恰好在这个时间点开始将所有的磁盘数据复制到磁带上。或者,其他时区的用户可能来访问你制作精美的Web 页面,也会导致繁重的流量。
  • 无线网络在这方面更具挑战性,因为它往往无法区分各种干扰源。即使附近没有其他无线网络在发送流量,或许有人在用微波炉爆玉米花,不经意间造成了干扰,从而降低802.11 性能。基于这些原因,良好的做法是监控整个网络的活动,这样你至少可以认识到何时发生了意想不到的事情。

小心使用粗粒度时钟

  • 计算机时钟的功能是以固定的时间间隔递增某个计数器。例如,一个毫秒计时器每隔1 毫秒计数器就加1 。使用这样的计时器来测量一个持续时间小于1 毫秒的事件是有可能的,但要非常小心。当然,有些计算机有更精确的时钟,但总会有时间更短的事件需要测量。请注意,时钟并不总是和返回的时间一样精确。例如,为了测量建立一个连接所需要的时间,应该在进入传输层代码以及离开传输层代码时,分别读出时钟值(比如说以毫秒为单位计数)。如果真正的连接建立时间是300 微秒,则两次读取的时间差值要么是0,要么是1 ,显然这两个结果都是错误的。然而,如果重复测量一百万次,把所有测量的总和累加起来,再除以一百万,则平均时间比1 微秒还要精确得多。

小心推断结果

  • 假设你利用模拟的网络负载来进行测量,网络负载从0 (空闲)到0.4 (40% 的容量)。例如,在802.11 网络上发送回语音包可以用如下图中的数据点和实线表示。如果能推断出随着负载增加而响应时间呈线性增长,如图中点线所示那样,那么结果是很诱人的。然而,许多排队论的研究结果都涉及一个1 /(1-p)因子,其中p 是负载,所以真正的值可能看起来更像是虚线,当负载变高时其上升速度远远高于线性增长。也就是说,竞争的影响在高负载下更为明显。在这里插入图片描述

3、针对快速网络的主机设计

  • 测量性能并进行修补可以在一定程度上提高网络性能,但是,它们不可能代替一个在一开始就有的良好设计。一个设计不佳的网络其得以改进的余地毕竟有限,除此之外,它必须从头开始重新设计。在本节中,我们将就主机实现网络协议提出一些经验法则。令人惊奇的是,经验表明通常的性能瓶颈不在快速网络而在于主机。这里存在两个原因。首先网络接口卡(NIC,Network Interface Cards )和路由器在工程上早己经能以“线速率”( wire speed )运行。这意味着它们处理数据包的速度和数据包到达链路的速度一样快。其次,相关的性能是指应用程序能获得的。它不是链路容量,而是经过网络和传输层处理之后的吞吐量和延迟。
  • 减少软件开销可以提高吞吐量和减少延迟,从而达到提高网络性能的目的。同时,它还能减少花在网络上的能量,能耗这个因素对于移动计算机是很重要的考虑。这些想法中的大多数多年来早己成为大多网络设计师必守的常识。

主机速度比网络速度更重要

  • 长期的经验表明在几乎所有的高速网络中,操作系统和协议开销占据着线路的主要实际时间。例如,从理论上讲, 1 Gbps 以太网上的最小RPC(远程过程调用)时间是1 微秒,对应着最小( 512字节)的请求和后续的一个最小( 512 字节)应答。实际上,克服了软件开销,随时随地使得RPC 时间接近理论值都是一个了不起的成就,但却很少真正发生。
  • 类似地,在1 Gbps 上运行的最大问题是应该足够快地将比特从用户缓冲区中取出放到网络上,以及接收主机以比特到达的速度来处理它们。如果你将主机( CPU 和内存)速度加倍,那么,你通常可以获得接近两倍的吞吐量。如果瓶颈在主机,那么加倍网络容量是没有效果的。

减少包技术来降低开销

  • 每个段都有特定数量的开销(例如,头)以及数据(比如有效载荷)。这两部分都需要消耗带宽,同时也都需要处理(例如,处理段头和计算校验和)。发送100 万字节时,不管段的大小是多大,数据成本是相同的。然而,长度为128 字节的段意味着每个段的开销是长度为4 KB段的开销的32 倍。带宽和处理开销加起来极大地降低了吞吐量。
  • 每个包在较低层次的开销放大了这种效果。如果主机速度跟得上,每个到达的数据包都会导致一次新的中断。在一个现代化的流水线处理器中,每次中断都要中断CPU 管道、干扰缓存、需要改变内存管理的上下文、废除分支预测表并强制保存大量的CPU 寄存器。因此把发送的段减少n 倍,可以降低n 倍的中断和数据包开销。
  • 你可能会说,人与计算机执行多任务的能力都很差。这种观察奠定了发送尽可能大MTU 数据包的需求,这样的MTU 能通过网络路径而无须分片。诸如Nagle 算法和Clark解决方案的一些机制都试图避免发送小的数据包。

最小化数据预取

  • 实现一个分层协议栈的最简单方法是每一层用一个模块实现。不幸的是,这将导致每一层重复许多工作(或至少通过多次传递才能访问到数据)。例如,在NIC 收到一个数据包后,它通常是把该包复制到内核缓冲区。从那里,它再被复制到一个网络层的缓冲区,供网络层实体处理:然后该包又被复制到传输层缓冲区,由传输层来处理:最终,由应用程序接收。对于一个入境数据包来说,在将它包含的段递交出去之前被复制三次或四次并不罕见。
  • 所有这些复制都大大降低了协议性能,因为内存操作比寄存器指令慢了一个量级。例如,如果20%的指令要对实际内存进行操作(即未命中高速缓存),这在预取入境数据包时是很有可能的,则平均指令执行时间要放慢2.8 倍( 0.8 × 1+0.2 × 10 )。这里,硬件辅助将无能为力。这个问题的根源在于操作系统执行了太多的复制操作。
  • 一个聪明的操作系统通过把多个层次的处理结合在一起,以此来最小化复制操作。例如, TCP 和IP 通常实现在一起(正如TCP/IP 所示的那样),这样当从网络层的处理切换到传输层的处理时,不再需要复制数据包的有效载荷。另一种常见的伎俩是在传递单个数据时在一层内执行多个操作。例如,在复制数据时通常要计算校验和(当必须要复制时),新近计算出的校验和可贴在尾部。

最小化上下文切换

  • 一个相关的规则说明上下文切换〈例如,从内核模式到用户模式〉是致命的。它们把中断和复制操作结合在一起,而这是个很坏的属性。这个成本就是为什么传输协议通常实现在内核中的理由。就像减少包计数一样,发送数据的库函数可以在内部进行缓冲直到它有大量的数据再发送,通过这种内部缓冲机制可以减少上下文切换。同样,在接收端,小的入境段应收集在一起一举传递给用户而不是个别地传递,以此最大限度地减少上下文切换。
  • 在最好的情形下,一个入境数据包导致从用户模式到内核模式的一次切换,然后再切换到接收进程并将新到达的数据交给它。不幸的是,在许多操作系统中,除此以外还需要额外的上下文切换。例如,如果网络管理器以特殊进程的形式运行在用户空间中,那么,一个数据包的到来可能引发一次从当前用户到内核的上下文切换:然后从内核切换到网络管理器:之后再切换回内核:最后从内核切换到接收进程。这个切换过程如图所示。在每个数据包上的所有这些上下文切换对CPU 时间是个严重浪费,同时也严重地影响了网络性能。在这里插入图片描述
    避免拥塞比从中恢复更好
  • “一分预防胜过十分治疗”这句古老的格言无疑特别适用于网络拥塞。当网络拥塞时,数据包被丢失,带宽被浪费,还引入了无用的延迟等一系列问题。所有为此付出的成本都是没有必要的,而且从拥塞中恢复还需要时间和耐心。最好的做法是从一开始就不让拥塞发生。

避免超时

  • 计时器在网络中是必要的,但应该尽量少用计时器,而且应该尽量少发生超时。当一个计时器超时,通常需要重复执行某个动作。如果确实需要重复执行这个动作,则执行该动作:否则,不必要的重复就是一种浪费。避免额外工作的办法是小心设置计时器的超时值,将计时器设置成稍稍超过一点保守时间边界。如果将计时器的超时间隔设置得太长,那么所在的连接(不太可能〉出现段丢失事件时会增加少量的额外延迟。如果一个计时器过早超时,则会消耗掉主机资源、浪费带宽,而且毫无理由地给很多路由器增加额外的负载。

4、快速处理段

  • 上述是通用规则,我们将考查某些加快段处理速度的特殊方法。段的处理开销由两部分组成:每个段的处理开销和每个字节的处理开销。这两部分都有改进的余地。快速处理段的关键是分离出一般情况和成功情况(单向数据传输),并对它们作特殊处理。许多协议倾向于强调出现某种错误情况时该怎么处理(比如,丢失了一个数据包〉,但是若要使得协议快速运行,协议的设计者应该把目标定在一切正常运行时如何最小化处理时间,而把出现问题时如何最小化处理放在次要地位考虑。
  • 尽管为了进入ESTABLISHED 状态需要一系列特殊的段,但一旦进入该状态,段的处理就是直截了当的,直到连接的某一端关闭连接。让我们从ESTABLISHED 状态下的发送端开始,看看它有数据要发送时的情形。为了清楚起见,假设传输实体运行在内核中,尽管同样的想法适用于其他的情形:传输实体是一个用户空间的进程,或者是发送进程内部的一个库。在下图中,发送进程陷入内核并执行SEND 。传输实体要做的第一件事情是测试,检查是否为正常情形:即状态必须为ESTABLISHED ,两端均不打算关闭当前连接,发送的是一个普通段(即不是带外数据〉,而且接收端有足够的窗口空间可供使用。如果上述所有的条件都满足,则无须进一步测试,使用发送端传输实体的快速路径。在通常情况下,这条快速路径占据了大部分的处理时间。在这里插入图片描述
  • 通常情况下,连续的数据段的头几乎是相同的。为了充分利用这个事实,传输实体在内部保存一个原型头。在快速路径的起始处,该原型头被尽可能快地逐字复制到一个临时缓冲区中。对于那些段与段之间不同的宇段,则复制时覆盖掉缓冲区中的相应字段。这些字段往往可以很容易地从状态变量中导出,比如“下一个序号”。然后,一个指向完整段头的指针和一个指向用户数据的指针被传递给网络层:因此,网络层可以遵循同样的策略。最后,网络层将结果数据包交给数据链路层传输。
  • 上述原理在实际中是如何工作的,我们用一个TCP/IP 的一个例子加以说明。下图(a)显示了TCP 头。在单向数据流中前后两个连续段有一些字段总是相同的,图中用阴影标识了这样的字段。发送端传输实体所要做的只是:将5 个字从原型头复制到输出缓冲区中,然后填充下一个序号(从内存中的一个字复制过来〉、计算校验和、递增内存中的序号:然后将头和数据交给一个特殊的IP 过程,由它来发送一个常规的、最大的段。紧接着, IP将它5 个字的原型头(如图b)复制到缓冲区中,然后填充标识(Identification)字段、计算校验和。现在这个数据包已经可以发送出去了(图a是TCP头,图b是IP头)。在这里插入图片描述
  • 现在让我们来看上上图中接收端的快速路径处理过程。第1 步是找到与入境段相对应的连接记录。对于TCP ,连接记录可能被保存在一张哈希表中,该哈希表把两个IP 地址和两个端口作为关键字执行某个简单函数。一且在该表中找到相应的连接记录,则比较两个地址和两个端口,以便验证找到了正确的连接记录。
  • 加速连接记录查询过程的一种优化措施是维护一个指向最近使用过的连接记录的指针,并且在开始查找时首先使用它。(Clark 等, 1989 )试用了这种方法,发现它的命中率超过90% 。
  • 找到了连接记录后,接收端就检查入境段,看它是否正常:连接状态是ESTABLISHED 、连接的两端均不打算关闭该连接、段完好无缺、段没有特殊的标志位,并且它的序号正好是接收端所期望的。这些测试都是一些指令。如果所有的条件都满足,则调用一个特殊的快速路径TCP 过程。
  • 快速路径更新连接记录,并且将数据复制给用户。在复制数据时,它同时计算校验和,从而消除了对数据的再次遍历操作。如果校验和正确,则更新连接记录,并返回发送端一个确认。这种首先快速检查头然后再详细处理的通用模式称为头预测( header prediction) ,即首先快速地检查段的头,确定该段是否自己所期望的段,然后再调用一个特殊的过程来处理。许多TCP 实现都使用了这种方法。当这种优化方案与本章中讨论的其他优化方案一起使用后,有可能使TCP 的运行速度达到本地内存到内存复制速度的90% ,这里假设网络本身的速度足够快。
  • 两个方面的性能有可能获得较大幅度的提高,它们分别是缓冲区管理和计时器管理。缓冲区管理中的主要问题是避免不必要的复制操作,正如我们上面介绍过的那样。计时器管理非常重要,因为几乎所有的计时器设置都不会超时。设置计时器是为了防止段的丢失,但是,大多数段和它们的确认都会正确地到达目的地。因此,在计时器很少出现超时的情况下,优化计时器的管理尤为重要。
  • 一种常见的方案是用链表结构将计时器事件按超时值进行排序保存。链表中的头表项包含一个计数器,指明了离超时时间还有多少个滴答数。每个后续表项也包含一个计数器,指明在前一个表项超时后还有多少个滴答。因此,如果3 个计时器分别在3 、10 和12 个滴答之后超时,则3 个计数器分别为3 、7 和2。每滴答一次,表头表项中的计数器被减1 。当它减到0 的时候,它的事件被处理,链表中的下一个表项变成链表的头。头表项中的计数器值不用改变。在这种方案中,插入和删除计时器是很昂贵的操作,其执行时间正比于链表的长度。
  • 如果最大的计时器间隔有上界,井且可以预先知道,那么我们可以使用一种更加高效的方法。这里,要用到一个称为计时轮( timing wheel )的数组,如图所示。每个槽对应于一个时钟滴答。图中显示的当前时间为T=4。三个计时器分别在从现在开始的3 、10 和12 个滴答时调度。如果一个新的计时器突然被设置成在7个滴答后超时,那么只需在第11 个槽中加入一个表项即可。类似地,如果要取消一个设置在T+10超时的计时器,则只要搜索第14 个槽中开始的链表,并将所请求的表项移除即可。请注意,图中的数组不可能容纳超过T+15 的计时器。在这里插入图片描述
  • 当时钟滴答时,当前时间指针向前移动一个槽(循环移动)。如果现在指向的表项不为0 ,则该表项中的所有计时器都要被处理。

5、头压缩

  • 我们很长以来一直在考查高速网络,那里还有更多的内容需要关注。现在让我们考虑无线网络和其他一些网络的性能,这些网络的带宽非常有限。降低软件开销有助于移动计算机运行得更加高效,但当网络链路成为瓶颈时,它对提高性能却是无能为力。
  • 为了更好地使用带宽,协议头和有效载荷应该携带尽可能少的比特。对于有效载荷来说,这意味着必须使用信息的压缩编码,比如JPEG 格式的图像,而不是位图或者诸如包含了压缩内容PDF 的文档格式。这也意味着应用程序级的缓存机制应该摆在首位,比如用降低传输的Web 缓存机制。
  • 协议头怎么样呢?在无线网络中的链路层,典型的头是压缩的,因为它们始终秉承着专为稀缺带宽而设计的思想。例如, 802.16 头采用了短的连接标识符,而不是长长的地址。然而,高层协议,比如IP 、TCP 和UDP 在所有链路层上采用的是同一版本,而且它们不是专为紧凑压缩头设计的。事实上,为减少软件开销而采用的流水型处理往往导致头无法压缩,而本来是可以做到的(例如, 1Pv6 有一个比IPv4 更松散的头)
  • 高层协议的头是一个重要的性能因素。考虑IP 语音数据,它通过IP 、UDP 和RTP 几个协议的组合传输。这些协议需要40 个字节长的头( IPv4 头20 字节, UDP 协议8 字节和RTP 协议头12 )。IPv6 的情况更糟:需要的头长达60 个字节,其中包括40 个字节的1Pv6报头。头占据了传输数据的大部分,并且消耗了一半多的带宽。
  • 头压缩( header compression )技术可用来降低高层协议头消耗的链路带宽,通常采用专门设计的方案,而不是通用的方法。这是因为头一般都很短,所以它们单独压缩的效果不那么好,而且解压缩时要求之前的所有数据都己经收到(如果之前的数据丢失了,解压缩的意义并不大,寒注)。显然,如果一个数据包丢失,就无法满足这个要求。
  • 使用协议格式的知识来压缩头可以获取巨大的收益。第一个方案由( Van Jacobson,1990 )设计,对通过低速串行链路上的TCP/IP 头进行压缩。它能够将一个典型的40 个字节的TCP/IP 头压缩到平均3 个字节。一个数据包与另一个数据包之间的许多头字段并没有改变。因为没有必要改变,例如,发送的每一个数据包中具有相同的IP TTL 字段或相同的TCP 端口号字段。这些字段可以在链路的发送端省略,在链路的另一端接收端填充上。
  • 类似地,其他字段以可预见的方式改变着。例如,除非丢失, TCP 序号随着数据发送而向前推进。在这种情况下,接收端可以预测到可能的值。即使如此,它可以是先前值的一个很小的变化,因为随着在相反方向收到的新数据,确认号也随之在递增。
  • 采用头压缩,高层协议的头就有可能非常简单,而且可以在低带宽链路上进行压缩编码。鲁棒头压缩(ROHC, RObust Header Compression )是头压缩的现代版本,作为一个框架由RFC 5795 定义。它的设计目标是能够容忍发生在无线链路上的丢失。每一组被压缩的协议都有一个轮廓( profile )文件,比如IP/UDP/RTP 。最终传输的压缩的头是携带一个指向上下文的引用,它本质上是一个连接:对于同一个连接上的数据包,其头中的字段可以很容易地预测出来,但不同的连接上的数据包头字段则无法预测。在典型的操作中,ROHC 将IP/UDP/RTP 头从40 个字节经过压缩降低到1 ~3 个字节。
  • 虽然头压缩的目标主要针对的是减少带宽需求,但它也有助于降低延迟。延迟由传播延迟和传输延迟两部分数据组成,前者对于给定的网络路径而言是固定的,而后者则取决于带宽和发送的数据量。例如,在1 Mbps 链路上发送1 比特需要1 微秒。在无线网络的介质上,网络速度相对较慢,因此传输延迟成为整体延迟中的一个重要因素,而且低延迟对于服务质量一贯重要。头压缩技术有助于减少发送的数据,从而降低传输延迟。发送较小的数据包,可以达到同样的效果。为了降低传输延迟,将增加软件开销。请注意,延迟的另一个潜在来源是访问无线链路的排队延迟(就是多个使用者竞争的情况,无线采用的CSMA/CA,即带有冲突避免的载波侦听多路访问,寒注)。这个延迟也很显著,因为作为网络中的有限资源,无线链路往往被过度地使用。在这种情况下,无线链路必须具备服务质量机制,给实时数据包以较低的延迟。仅仅进行头压缩是不够的。

6、长肥网络的协议

  • 20 世纪90 年代初,出现了长距离传输数据的千兆网络。由于结合了快速网络或“肥管道” (fat pipeline )和长延迟,这些网络称为长肥网络。当这些网络出现时,人们的最初反应是使用已有的协议,但是很快各种各样的问题随之出现。在这一小节中,我们将讨论随着网络协议的速度和延迟尺度增加会出现的一些问题。
  • 第一个问题是许多协议使用了32 位长的序号。当Internet 刚开始时,路由器之间的线路主要是56 kbps 的租用线路,所以一台全速发送数据的主机需要一星期的时间才可能用完一轮序号(即导致序号回绕)。对于TCP 的设计者们来说, 232 是一个相当体面的无穷大近似数,因为一周以前发送的老数据包仍然停留在网络中的危险性几乎不存在:对于10 Mbps 以太网,序号回绕时间变成了57 分钟,尽管时间更短了,但仍然可以管理:对于1 Gbps 以太网,如果主机全速发送数据到Internet 上,则序号回绕时间大约是34 秒钟,大大低于Internet 上的最大数据包生存期,即120 秒。而且,当老的数据包仍然存在网络中时,快速发送端就开始循环使用序号空间了。
  • 问题在于许多协议的设计者简单地认为使用完整序号空间所需要的时间大大超过包的最大生存期,而且这种假设还没有声明。因此,没有必要甚至不用担心序号回绕时老的重复数据包仍然存在这个问题。但是对千兆位的速度,这种未声明的假设无疑是失败的。幸运的是,己经证明可以通过采用时间戳来扩展有效的序号范围,这个时间戳作为TCP 头的选项作为以高序列比特的形式被每个数据包携带着。这种机制称为防止序号回绕( PAWS,Protection Against Wrapped Sequence numbers ),在RFC1323 文档中有详细描述。
  • 第二个问题是流量控制窗口的大小必须增长得很快。例如,考虑从圣地亚哥发送一个64KB的突发数据到波士顿,以便填满接收端的64 KB缓冲区。假设链路速率1 Gbps,光在光纤中的单向延迟为20 毫秒。最初,在t= 0,管道是空的,如图 (a )所示。500 微秒后,如图(b )所示所有的段都被发送到光纤上了。前面的段现在出现在Brawley (地名)附近的某个地方,仍然位于南加州的腹地。然而,发送端必须停止,直到它收到一个窗口更新段(可能接收端窗口满了,寒注)。在这里插入图片描述
  • 20 毫秒后,先遣段到达波士顿,如图c所示,并得到确认。最后,在开始发送后40 毫秒,第一个确认返回到发送端,然后开始发送第二次突发数据块。由于传输线路只使用了100 中的1.25 毫秒(0.5微秒/40毫秒),因此其效率大约是1.25% 。这是老协议运行在千兆线路上的典型情况。
  • 在分析网络性能时要时刻牢记的一个有用数值——带宽延迟乘积。它是往返延迟时间(秒)乘以带宽(比特/秒)。这个乘积就是从发送端到接收端并且返回的管道的容量(比特)。
  • 对于图中的例子来说,带宽延迟乘积是40 个百兆比特。换句话说,发送端必须突发40 个百兆的比特才能在第一个确认返回前保持全速传输。也就是说,需要这么多个位来填充管道(在两个方向上)。这就是为什么突发百兆位的一半(64KB/s=0.512Mbps,寒注)只能达到1.25% 的效率:它仅为管道容量的1.25% 。这里可以得出的结论是为了获得良好的性能,接收端的窗口必须至少和带宽时延积一样大,最好再大点,因为接收端可能无法立即响应。对于一个跨洲的千兆线路,需要至少5MB(即40个兆比特)。
  • 第三个相关问题是简单重传策略,比如回退N 协议,在一条带宽延迟乘积非常大的线路上性能非常差。考虑一条1 Gbps 横贯大陆的线路,其往返传输时间是40 毫秒。在这段时间中发送端可以传输5MB的数据。如果一个错误被接收端检测出来,那么40 毫秒以后发送端才能接到错误通知。如果使用回退N 协议,则发送端不仅要重传坏的数据包,而且要重传该数据包后面的5MB 数据(因为这种协议必须按顺序接收数据包)。很明显,这是资源的极大浪费,因此需要更复杂的协议,例如选择重传协议。
  • 第四个问题是千兆位线路与百兆位线路在本质上的不同,长距离的千兆位线路的制约因素是延迟而不是带宽。在下图中,我们看到将一个1 Mb 文件以不同的传输速度传输4000 千米所需要的时间。在速度增加到1 Mbps 以前,传输时间主要受到发送速率的制约:超过1 Gbps 时, 40 毫秒的往返延迟时间远远超过了将数据发送到光纤上所需要的1毫秒时间。此时,进一步增加带宽也不会有任何帮助。在这里插入图片描述
  • 上图的情形对网络协议由一些不幸的影响。从图中可以看出,比如像RPC这样的停-等式协议其性能有一个固有的上界。这种限制来自于光速的限制,光学的技术再怎么进步也无法改善这种状况。除非在一台主机等待应答时千兆线路可以用作一些其他用途,否则千兆线路比百兆线路没什么好的,只是更昂贵而已。
  • 第五个问题是通信速度己经得到很大提高, 远远超越了计算速度。在20 世纪70 年代, ARPANET只能运行在56 kbps 的线路上,而当时的计算机已经达到1 MIPS (单字长定点指令平均执行速度 Million Instructions Per Second的缩写,每秒处理的百万级的机器语言指令数。这是衡量CPU速度的一个指标。像是一个Intel 80386 电脑可以每秒处理3百万到5百万机器语言指令,即我们可以说80386是3到5MIPS的CPU。MIPS只是衡量CPU性能的指标)的计算速度。将这些数字与在1 Gbps 线路上交换数据包的1000MIPS 计算机进行比较。每个字节的指令数量已经下降了超过10 倍。确切的数字值得商榷,具体依赖于测试日期和场景,但由此得出的结论是:协议处理的可用时间少于过去协议处理所用的时间,因此协议必须变得更加简洁。
  • 现在让我们从存在的问题转到处理这些问题的办法上来。所有高速网络设计者必须牢记在心的基本原则是:为速度而不是为带宽优化进行设计。老协议的设计目标通常是最小化线路上传输的比特个数, 一般的做法是使用小的字段,并且将这些小的字段组合成字节或者字。这种关注对于无线网络依然有效,但对于千兆位的快速网络不再适用。协议处理是个问题,所以,协议的设计重点变成如何将协议本身最小化。显然, IPv6 的设计者们清楚这条原则。
  • 一种很吸引人的加速办法是用硬件来构建快速网络接口。这种策略的困难在于除非协议极其简单,否则,硬件就是带有第二个CPU 和自己独立程序的一块插卡。为了确保网络协处理器( network coprocessor )比主CPU 便宜,它通常是一块慢速芯片。这种设计的直接结果是主(快速) CPU 的许多时间是空闲的,它要等待第二个(慢速) CPU 完成关键性的工作。认为主CPU 在等待期间可以去做其他工作的想法是不切实际的。而且,当两个通用CPU 相互通信时,可能会产生竞争条件,所以两个处理器之间的通信协议需要精心设计,以便保证两者能正确地同步并且避免竞争。一般来说,最好的途径是使协议尽可能的简单,并且让主CPU 来完成协议处理工作。
  • 数据包的布局结构也是千兆网络中一个很重要的考虑因素。头应该尽可能包含少的字段,以便减少包的处理时间,而且头中的这些字段应该足够大到正常工作,另外,这些字段应该按字对齐以便于快速处理。在这里的上下文中, “足够大”意味着类似于下面的问题不会发生:比如序号回绕时老的数据包仍然存在,或者由于窗口宇段太小导致接收端不能宣告足够大的窗口空间。
  • 为了降低软件开销和有效操作,最大的数据长度应该非常大。对于高速网络来说, 1500个字节太小,这就是为什么千兆以太网支持大到9阻的巨型数据帧以及IPv6 支持大于64 KB的大块数据包传输的理由。
  • 现在我们来看高速协议中的反馈问题。由于(相对〉较长时间的延迟回路,应该尽可能地避免反馈:接收端给发送端发送信号需要太长的时间。第一个反馈例子是利用滑动窗口协议来控制传输速率。为了避免由于接收端给发送端发送窗口更新信息而造成固有的(长时间〉延迟,未来的协议最好使用基于速率的协议,这样才能避免接收端发送窗口更新段给发送端所带来的固有的(长〉延迟。在这样的协议中,发送端可以发送所有它希望传送的数据,只要发送速率不超过双方预先协商好的速率即可。
  • 第二个反馈例子是Jacobson 的慢速启动算法。这个算法需要执行多次探测来确定网络的处理能力。对于高速网络,执行几次小的探测才能确定网络的响应能力将浪费大量带宽。一种更加有效的方法是让发送端、接收端和网络三者在建立连接时都预留下必要的资源。提前预留资源还有另一个好处,就是更加容易减少抖动。简而言之,网络越是向高速发展,设计就越是被无情地推向面向连接的操作,或者非常接近于面向连接的操作。另一个有价值的特性是在连接请求过程中顺带发送正常量数据的能力。按照这种方法,可以节省一次往返时间。

猜你喜欢

转载自blog.csdn.net/ao__ao/article/details/88595744