过去几年,我们在移动蜂窝网络性能方面取得了重大进展。但是,由于网络延迟膨胀,许多移动应用程序无法充分利用这一进步。
延迟长期以来一直是移动网络的代名词。尽管近年来取得了进展,但网络延迟的减少速度赶不上速度的提高。由于这种差异,延迟而不是吞吐量通常是限制网络交易性能的因素。
本章有两个逻辑部分。第一部分将探讨导致延迟问题的移动蜂窝网络的细节。在第二部分中,将介绍用于最大程度地减少高网络延迟的性能影响的软件技术。
延迟表示数据包跨越网络或一系列网络传输所需的时间。移动网络通过多种因素增加了大多数基于互联网的通信中已经存在的延迟,包括网络类型(例如,HSPA+ 与 LTE),运营商(例如,AT&T 与 Verizon)或情况(例如,站立与驾驶,地理位置,时间,等等)。很难说出移动网络延迟的准确值,但可以发现它在几十毫秒到几百毫秒之间变化。
往返时间 (RTT) 是衡量数据包从源到目的地再返回的延迟的指标。往返时间对许多网络协议的性能有压倒性的影响。这可以通过著名的乒乓球运动来说明。
在常规的乒乓球比赛中,球在球员之间移动所需的时间几乎不可察觉。但是,当球员站得越来越远时,他们开始花更多的时间等待球,而不是做任何其他事情。如果球员相隔一千英尺,那么以规则距离进行的 5 分钟乒乓球比赛将持续几个小时,无论这听起来多么荒谬。用客户端和服务器代替 2 个玩家,用往返时间代替玩家之间的距离,你就会开始看到问题所在。
大多数网络协议在正常操作过程中都进行着乒乓球游戏。这些来回,如果你愿意,是建立和维护逻辑网络会话(例如,TCP)或执行服务请求(例如,HTTP)所需的往返消息交换。在这些消息交换过程中,很少或根本没有数据传输,网络带宽在很大程度上没有被使用。延迟在很大程度上加剧了这种利用不足的程度;每次消息交换都会导致至少网络往返时间的延迟。这种累积的性能影响是显著的。
考虑一个下载 10KiB 对象的 HTTP 请求,这将涉及 4 次消息交换。现在假设往返时间为 100ms(对于移动网络来说相当合理)。将这两个数字都考虑在内,我们得到 10KiB 每 400ms 的有效吞吐量,或 25KiB 每秒。
请注意,在前面的例子中,带宽完全无关紧要——无论网络速度有多快,结果都一样,25KiB/s。只有通过一项明确的策略才能提高之前操作或类似操作的性能:避免网络客户端和服务器之间的往返消息交换。
以下是对移动蜂窝网络组件和约定的简化介绍,这些组件和约定是延迟难题的一部分。
移动蜂窝网络由一系列相互连接的组件表示,这些组件具有高度专业化的功能。这些组件中的每一个都是以某种方式导致网络延迟的因素,但程度不同。蜂窝网络中存在独特的约定,例如无线资源管理,这些约定也是移动网络延迟方程的一部分。
图 10.1 - 移动蜂窝网络的组件
大多数移动设备内部实际上有两台非常复杂的计算机。应用程序处理器负责托管操作系统和应用程序,类似于您的计算机或笔记本电脑。基带处理器负责所有无线网络功能,类似于使用无线电波而不是电话线进行连接的计算机调制解调器。1
基带处理器是一个一致但通常可以忽略的延迟源。高速无线网络是一件令人恐惧的复杂事情。它所需的复杂信号处理会对大多数网络通信造成一定的固定延迟,范围从微秒到毫秒。
一个小区基站,与收发机基站或手机塔同义,充当移动网络的接入点。小区基站负责在一个称为小区的区域内提供网络覆盖。
与它所服务的移动设备一样,小区基站也因高速无线网络相关的复杂处理而负担过重,并且贡献了相同的几乎可以忽略的延迟。但是,小区基站必须同时为数百到数千个移动设备提供服务。系统负载的变化将导致吞吐量和延迟的变化。拥挤的公共活动中缓慢、不可靠的网络性能通常是由于小区基站的处理限制达到极限而造成的。
最新一代的移动网络已经扩展了小区基站的作用,使其包括直接管理其移动设备。许多以前由无线网络控制器负责的功能,例如网络注册或传输调度,现在由小区基站处理。出于本章后面将解释的原因,这种角色转变解释了最新一代移动蜂窝网络所取得的延迟降低的大部分原因。
回程网络是小区基站、其控制器和核心网络之间的专用WAN连接。回程网络长期以来一直是,并且仍然是延迟的臭名昭著的贡献者。
回程网络延迟传统上源于在较旧的移动网络(例如,GSM,EV-DO)上使用的电路交换或帧传输协议。由于它们的同步性质,此类协议会表现出延迟,其中逻辑连接由一个通道表示,该通道可能只在短暂的预先分配的时间段内接收或传输数据。相比之下,最新一代的移动网络采用支持异步数据传输的基于IP的数据包交换回程网络。这种转换大大减少了回程延迟。
物理基础设施的带宽限制是一个持续的瓶颈。许多回程网络并非为处理现代高速移动网络能够承受的峰值流量负载而设计,并且通常在变得拥塞时会表现出延迟和吞吐量的很大差异。运营商正在尽力尽快升级这些网络,但这一组件仍然是许多网络基础设施中的一个薄弱环节。
传统上,无线网络控制器管理相邻小区基站及其所服务的移动设备。
无线网络控制器使用基于消息的管理方案(称为信令)直接协调移动设备的活动。由于拓扑结构,移动设备和控制器之间的所有消息流量都必须通过高延迟回程网络传输。仅此一项并不理想,但更糟糕的是,许多网络操作(例如网络注册和传输调度)需要多次来回消息交换。传统上,无线网络控制器一直是延迟的主要贡献者,原因就在于此。
如前所述,在最新一代的移动网络中,控制器免除了其设备管理职责,其中大部分任务现在由小区基站本身直接处理。这个设计决策消除了许多网络功能中的回程延迟因素。
核心网络充当运营商专用网络和公共互联网之间的网关。运营商在其中使用内联网络设备来执行服务质量策略或带宽计量。一般来说,任何对网络流量的拦截都会引入延迟。在实践中,这种延迟通常可以忽略不计,但应该注意它的存在。
移动网络延迟最重要的来源之一与移动电话电池的有限容量直接相关。
高速移动设备的网络无线电在运行时可以消耗超过 3 瓦的功率。这个数字大到足以在不到一个小时内耗尽 iPhone 5 的电池。为此,移动设备会尽一切可能关闭或降低无线电电路的电源。这对于延长电池寿命来说是理想的,但也会在无线电电路重新通电以传送或接收数据时引入启动延迟。
所有移动蜂窝网络标准都正式化了一种无线资源管理 (RRM) 方案来节省电能。大多数RRM约定定义了三种状态——活动、空闲和断开连接——它们分别代表了启动延迟和功耗之间的某种折衷。
图 10.2 - 无线资源管理状态转换
活动表示可以以高速率传输和接收数据且延迟最小的状态。
即使在空闲时,这种状态也会消耗大量的能量。网络短暂的非活动,通常不到一秒钟,就会触发向功耗较低的空闲状态的转换。需要注意的是,这种转换的性能影响:在网络事务过程中,足够长的暂停会导致额外的延迟,因为设备会在活动状态和空闲状态之间波动。
空闲是对较低功耗和中等启动延迟的一种折衷方案。
该设备保持连接到网络,无法传输或接收数据,但能够接收需要活动状态才能满足的网络请求(例如,传入数据)。经过一段合理的网络非活动时间,通常为一分钟或更短,设备将进入断开连接状态。
空闲通过两种方式导致延迟。首先,它需要一些时间让无线电重新通电并同步其模拟电路。其次,为了节省更多的能量,无线电只间歇地监听,并稍微延迟对网络通知的任何响应。
断开连接具有最低的功耗和最大的启动延迟。
设备断开与移动网络的连接,无线电关闭。无线电会不定期地激活以监听通过专用广播信道到达的网络请求。
断开连接与空闲连接具有相同的延迟来源,此外还包括网络重新连接的额外延迟。连接到移动网络是一个复杂的过程,涉及多轮消息交换(例如,信令)。至少,恢复连接需要数百毫秒,并且看到连接时间在秒内并不罕见。
现在让我们来看看我们可以控制的东西。
网络事务的性能受到膨胀的往返时间的影响。这是由于大多数网络协议的操作固有的往返消息交换。本章的其余部分侧重于了解为什么这些消息交换正在发生以及如何减少或甚至消除它们的频率。
图 10.3 - 网络协议
传输控制协议(TCP)是一种面向会话的网络传输,建立在IP网络约定之上。TCP影响其他协议(如HTTP 或TLS)所需的无错误双工通信通道。
TCP 展示了许多我们试图避免的往返消息传递。一些可以通过采用协议扩展(如快速打开)来消除。其他可以通过调整系统参数(如初始拥塞窗口)来最小化。在本节中,我们将探讨这两种方法,同时还提供一些关于TCP 内部结构的背景信息。
启动TCP 连接涉及一个三部分消息交换约定,称为三次握手。TCP 快速打开(TFO)是TCP 的一个扩展,它消除了握手过程通常导致的往返延迟。
三次握手协商客户端和服务器之间的操作参数,这些参数使得可靠的双向通信成为可能。初始SYN(同步)消息代表客户端的连接请求。如果服务器接受连接尝试,它将回复SYN-ACK(同步和确认)消息。最后,客户端用ACK消息确认服务器。此时,已形成逻辑连接,客户端可以开始发送数据。如果你在记分,你会注意到,三次握手至少会引入相当于当前往返时间的延迟。
图 10.4 - TCP 三次握手
传统上,除了连接回收之外,没有办法避免三次握手的延迟。然而,随着TCP 快速打开IETF 规范的引入,这种情况最近发生了改变。
TCP 快速打开(TFO)允许客户端在逻辑上建立连接之前开始发送数据。这有效地抵消了三次握手带来的任何往返延迟。这种优化的累积效果令人印象深刻。根据谷歌研究,TFO 可以将页面加载时间缩短多达 40%。尽管目前只是一个草案规范,但TFO 已得到主要浏览器(Chrome 22+)和平台(Linux 3.6+)的支持,其他供应商也承诺很快完全支持它。
TCP 快速打开是对三次握手的一种修改,它允许将少量数据有效载荷(例如HTTP 请求)放在SYN 消息中。此有效载荷在连接握手完成时传递给应用程序服务器,就像其他情况一样。
早期扩展提案,如TFO 最终因安全问题而失败。TFO 使用安全令牌或cookie的概念解决了这个问题,该令牌或cookie 在传统TCP 连接握手过程中分配给客户端,并预期包含在TFO 优化的请求的SYN 消息中。
使用TFO 有一些轻微的注意事项。最值得注意的是,对于与启动SYN 消息一起提供请求数据的任何幂等性保证的缺乏。TCP 确保接收方忽略重复数据包(重复现象经常发生),但这种保证不适用于连接握手。正在努力在草案规范中标准化解决方案,但在此期间,TFO 仍然可以安全地部署用于幂等事务。
初始拥塞窗口(initcwnd)是一个可配置的TCP 设置,具有加速较小网络事务的巨大潜力。
最近的IETF 规范 促进了将常见的初始拥塞窗口设置从 3 个段(即数据包)增加到 10 个。该提案基于谷歌进行的广泛研究,该研究表明平均性能提高了 10%。在没有介绍TCP 的拥塞窗口(cwnd)的情况下,无法理解此设置的目的和潜在影响。
TCP 在通过不可靠网络运行时为客户端和服务器保证可靠性。这相当于一个承诺,所有数据都会像发送时那样被接收,或者至少看起来是这样。数据包丢失是满足可靠性契约的最大障碍;它需要检测、纠正和预防。
TCP 使用正向确认约定来检测丢失的数据包,其中每个发送的数据包都应得到其预期接收方的确认,如果缺少确认,则意味着它在传输过程中丢失了。在等待确认时,传输的数据包保存在一个称为拥塞窗口的特殊缓冲区中。当该缓冲区已满时,会发生称为cwnd 耗尽的事件,所有传输都会停止,直到接收方确认腾出空间以发送更多数据包。这些事件在TCP 性能中发挥着重要作用。
除了网络带宽的限制之外,TCP 的吞吐量最终受到 cwnd 耗尽事件频率的限制,其可能性与拥塞窗口的大小相关。实现峰值TCP 性能需要一个与当前网络条件相辅相成的拥塞窗口:太大,它会造成网络拥塞——一种由大量数据包丢失造成的拥挤状态;太小,宝贵的带宽就会浪费。合乎逻辑的是,对网络条件了解得越多,选择最佳拥塞窗口的可能性就越大。现实情况是,关键的网络属性(如容量和延迟)难以衡量,而且一直在变化。更复杂的是,任何基于互联网的TCP 连接都将跨越多个网络。
缺乏意味着准确地确定网络容量,TCP 反而从网络拥塞的状态中推断出来。TCP 将扩展拥塞窗口,直到它开始看到数据包丢失,这表明某个下游网络无法处理当前的传输速率。使用这种拥塞避免方案,TCP 最终将 cwnd 耗尽事件最小化,直到它消耗了它被分配的所有连接容量。最后,我们终于找到了TCP 初始拥塞窗口设置的目的和重要性。
没有数据包丢失的迹象就无法检测到网络拥塞。一个新的或空闲的连接缺乏建立最佳拥塞窗口大小所需的数据包丢失证据。TCP 采用了一种策略,即最好从最不可能造成拥塞的拥塞窗口开始;这最初意味着设置为 1 个段(约 1480 字节),并且一段时间以来,这是推荐的设置。后来的实验表明,高达 4 个的设置可能有效。在实践中,你通常会发现初始拥塞窗口设置为 3 个段(约 4 KiB)。
初始拥塞窗口对小型网络事务的速度不利。这种影响很容易说明。在标准设置 3 个段的情况下,cwnd 耗尽将在仅发送 3 个数据包或 4 KiB 后发生。假设数据包是连续发送的,相应的确认将不会早于连接的往返时间允许的时间到达。例如,如果RTT 为 100 毫秒,则有效传输速率将是可怜的 400 字节/秒。虽然TCP 最终会扩展其拥塞窗口以完全消耗可用容量,但它的启动速度非常慢。事实上,这种约定被称为慢启动。
在慢启动影响较小下载性能的范围内,它要求重新评估初始拥塞窗口的风险回报主张。谷歌做了这样的事情,发现 10 个段(约 14 KiB)的初始拥塞窗口为最少的拥塞产生了最大的吞吐量。现实世界中的结果表明,页面加载时间总体减少了 10%。往返延迟较高的连接将获得更大的效果。
从默认值修改初始拥塞窗口并非易事。在大多数服务器操作系统下,它是一个系统范围的设置,只能由特权用户配置。这种设置很少能在客户端由非特权应用程序配置,甚至根本无法配置。重要的是要注意,服务器上较大的初始拥塞窗口会加速下载,而在客户端上则会加速上传。无法在客户端更改此设置意味着应该特别努力地最小化请求有效载荷大小。
本节讨论了缓解高往返延迟对超文本传输协议(HTTP)性能影响的技术。
保持活动是一个HTTP 约定,它允许在连续请求中使用相同的TCP 连接。至少避免了一次往返——TCP 三次握手所需的一次往返——每次请求节省了数十或数百毫秒。此外,保持活动还具有额外的,并且经常被忽视的性能优势,即在请求之间保留当前TCP 拥塞窗口,从而导致更少的 cwnd 耗尽事件。
图 10.5 - HTTP 管道
实际上,管道将网络往返的延迟分配给多个HTTP 事务。例如,在 100 毫秒的RTT 连接上,5 个管道化的HTTP 请求将产生 20 毫秒的平均往返延迟。对于相同的条件,10 个管道化的HTTP 请求将平均延迟减少到 10 毫秒。
HTTP 管道存在一些显着的缺点,这些缺点阻止了其更广泛的采用,即HTTP 代理支持的历史记录不佳,以及容易受到拒绝服务攻击。
传输层安全(TLS)是一种面向会话的网络协议,允许在公共网络上安全地交换敏感信息。虽然TLS 在保护通信方面非常有效,但在高延迟网络上运行时,其性能会下降。
TLS 采用了一个复杂的握手,涉及两次客户端-服务器消息交换。TLS 安全的HTTP 事务可能由于这个原因而显得明显更慢。通常,关于TLS 速度慢的观察实际上是对其握手协议引入的多个往返延迟的抱怨。
图 10.6 - DNS 查询
通常,托管平台提供缓存机制以避免频繁的 DNS 查询。 DNS 缓存的语义很简单。每个 DNS 响应都包含一个生存时间(TTL)属性,声明结果可以缓存多长时间。TTL 的范围可以从几秒到几天,但通常为几分钟。极低的 TTL 值,通常不到一分钟,用于影响负载均衡或将服务器更换或 ISP 故障转移造成的停机时间降至最低。
大多数平台的原生 DNS 缓存实现没有考虑移动网络的较高往返时间。许多移动应用程序可以从增强或替换默认解决方案的缓存实现中获益。本文建议了几种缓存策略,如果将其用于应用程序,将消除由不必要的 DNS 查询引起的任何随机和虚假延迟。
高可用性系统通常依赖于在其 IP 地址空间内托管的冗余基础设施。低 TTL DNS 条目可以减少网络客户端可能引用故障主机地址的时间,但同时会触发大量额外的 DNS 查询。 TTL 是在最小化停机时间和最大化客户端性能之间的一种折衷。
当服务器故障只是例外情况时,没有必要普遍降低客户端性能。解决此难题有一个简单的方案,而不是严格遵守 TTL,缓存的 DNS 条目仅在更高层协议(如 TCP 或 HTTP)检测到不可恢复的错误时刷新。在大多数情况下,此技术模拟了符合 TTL 的 DNS 缓存的行为,同时几乎消除了通常与任何基于 DNS 的高可用性解决方案相关的性能损失。
需要注意的是,此缓存技术可能与任何基于 DNS 的负载分配方案不兼容。
异步刷新是一种 DNS 缓存方法,它(基本上)遵守发布的 TTL,同时在很大程度上消除了频繁 DNS 查询的延迟。需要异步 DNS 客户端库,例如 c-ares,才能实现此技术。
想法很简单,对过期 DNS 缓存条目的请求会返回陈旧的结果,同时在后台调度一个非阻塞 DNS 查询来刷新缓存。如果使用回退到阻塞(即同步)查询(用于非常陈旧的条目),此技术几乎不受 DNS 延迟的影响,同时还与许多基于 DNS 的故障转移和负载分配方案兼容。
减轻移动网络膨胀延迟的影响需要减少加剧其影响的网络往返次数。采用专门针对最小化或消除往返协议消息的软件优化对于克服这一艰巨的性能问题至关重要。