在 Web 的早期,我们严重缺乏工具和框架,现在回想起来,那些早期的 Web 服务竟然能够扩展,这似乎是值得注意的。如今,虽然工具已经进步,但人们对交互的丰富性、性能和可扩展性的期望也随之提高。鉴于这些提高的期望,明智的做法是只构建你真正需要的,尽可能依赖他人的工作。最重要的是,在选择何时、何物以及如何优化时要谨慎。
我在亚马逊参加的第一次与可扩展性相关的会议的主题是“为假期扩展”。日期是 1998 年 6 月 3 日。Bob Vadnais 主持了会议,由于没有会议室,会议地点在他的公寓里。Bob 可以完美地完成其他工程师甚至无法想象的鱼跃救球,很明显,度过那个假期更多地取决于英雄般的努力,而不是毫不费力的可扩展架构。我们在那次会议上只讨论了两种策略:第一种是更大的服务器,第二种是调优。这是一个扩大规模以满足预期需求的问题。
当时,亚马逊网站即将迎来第三个年头,并获得了在当时看来令人印象深刻的流量,但我们的重点是客户体验和尽可能快地增长。当时的口号是“快速做大”。对增长的重视是恰当的,但我们明白,当需要关注架构健全且可持续的可扩展性时,这将更具挑战性。
现在,和那时一样,风险投资支持的科技创业公司的成功率约为十分之一。因此,如果你被要求构建可扩展的 Web 服务,你可能想问:“你确定吗?” 花在优化可扩展性上的时间和资源可能更好地用于改善客户体验和推动流量。在你构建网站和增长流量的过程中,或许有可能在未来的可扩展性方面做到无害或最小程度的损害。
当我们开始构建基础设施 Web 服务(例如 S3(简单存储服务)和 EC2(弹性计算云))时,我们已经学到了很多关于大型 Web 服务如何扩展,或者有时不扩展的知识,并且我们有一套完善的需求。
在过去的 10 年里,构建大型动态 Web 服务的准入门槛已大幅降低。三个重要的发展以不同的方式促进了准入门槛的降低:面向服务架构 (SOA) 的趋势、云计算基础设施服务的兴起以及 Web 应用程序框架(如 ASP.NET、Django、Rails 和 Spring)的可用性。
这些发展极大地促进了模块化和更好的关注点分离。它们还将新的责任分离带入视野。重要的是只构建只有你才能构建的东西,尽可能依赖他人的工作或服务。花在构建或定制 Web 应用程序框架或构建基础设施上的时间和资源可能更好地用于改进业务逻辑。每个人都需要框架和基础设施,但它们几乎不提供增量客户价值,因此花在构建它们上的时间就是花在无差异的繁重工作上的时间。
在亚马逊的早期,将流量模式推到高斯模型预测之外的事件通常涉及国家媒体的显着报道。在美国,由此产生的流量峰值因我们的美国客户分布在不同的时区而被削弱——并非每个人都在同一时间阅读报纸或观看“奥普拉”。当我们扩展到社会凝聚力更强的单一时区市场(如德国)时,重要的媒体曝光导致了更尖锐的峰值;然而,即使在那里,最急剧的请求速率转换也往往发生在重要足球比赛的开始和结束时。
在最近对决策类型和不同类别的随机性对结果的影响的考察中,Nicholas Nassim Taleb 重温了他所谓的“黑天鹅”,即具有巨大影响的高度不可能和不可预测的事件。4 他认为,在金融和商品市场等不可预测(且经常被误解)的波动领域,对效率的追求会增加脆弱性。例如,由于缺乏余量,商品价格可能会在需求短暂爆发时翻倍。他的建议:“避免优化,学会热爱冗余。”
大型(以及小型)Web 服务的运营商非常关注容量优化和服务器利用率最大化。在当前的经济环境下,这种关注可能会加强。
不幸的是,互联网流量模式有时可能看起来属于 Taleb 所谓的“极端斯坦”。曾经被称为“Slashdot 效应”(由许多互联网用户一致行动引起的流量过载)现在更常见,幅度也更高,这是由于更持续的网络访问、社交图谱的紧密性增强、元博客的采用以及社交网络和智能手机应用程序的病毒式传播。这还不包括恶意生成的流量洪水。此外,意外事件可能会影响容量供应方面,原因从低效的软件发布到外部事件(如 2003 年 8 月的美国东北部停电)不等。冗余通常只被视为提高可用性的策略(通过允许绕过故障组件进行路由)。它也应被视为在极端事件期间保持供需平衡的策略。
Animoto 是一款 Web 应用程序,它使用人工智能生成专业制作的音乐视频。该公司于去年四月在 Facebook 上发布了它,在 Amazon EC2 上运行。几天来,它平均运行在约 40 台服务器上,标准偏差为个位数。正如社交网络应用程序有时会发生的情况一样,Animoto 突然变得流行起来,并在三天内使用了 3,500 台服务器。对于这种程度的横向扩展,容量必须是弹性的且无摩擦的;如果你在不使用它时不会承担成本或冗余损失,那将是一个额外的好处。
在建模预期流量,然后构建非常精确的可扩展性计划以满足该目标时,存在危险。好的模型很难构建,并且可能会因简化或乐观的假设而受到影响,这些假设会低估可变性。引用 Taleb 的话,你不能“使用不确定性模型来产生确定性”。更大的危险在于:如果你的 Web 服务成功,你最终会看到比目标模型建议的更大的需求——也许不是这个黑色星期一或超级碗星期日,但也许很快之后,并且是在一个不太预期的时间。
理想情况下,规模测试应在与生产环境无法区分的环境中运行,并运行到崩溃点。一个流行的崩溃点测试示例是“波音 777 机翼负载测试”。1 除了分析首先崩溃的是什么以及原因之外,我们还要寻找给定的应用程序或服务如何在没有损坏或丢失的部件的情况下取得进展,然后重新运行测试以确定下一个崩溃点,有时会引发与 Monty Python“黑骑士”场景的比较。
大型 Web 服务运营中最困难的问题之一是如何实施高保真测试环境。没有神奇的解决方案,但我们再次发现,通过在我们的计算云中使用虚拟化资源,这个问题变得更容易处理。我们可以实现更高程度的保真度(通过运行相同的系统映像)和隔离,在如何启动和停止测试方面具有更大的灵活性,捕获结果和问题以供后续分析,并更有效地利用资源。
构建可扩展的 Web 服务中最困难的挑战是如何在存在故障和极端并发访问模式的情况下,处理持久性、可靠性、性能和成本效益之间的权衡。
这种挑战在持久层中尤为明显。在本期 Queue 中,Amazon.com 的 Werner Vogels 讨论了拥抱“最终一致性”如何帮助克服构建全球规模可靠系统的挑战。在 Queue 2008 年 5 月/6 月刊中,eBay 的 Dan Pritchett 从不同的角度审视了这一持久性挑战。2
Sun Microsystems 的 Craig Russell 也在 Queue 2008 年 5 月/6 月刊中讨论了 ORM(对象关系映射)。3 ORM 正在获得广泛采用,并带来可扩展性方面的考虑。借助 ORM,持久层中存储的数据在应用程序中表示为本机对象编程语言中的对象,从而抽象了持久性实现细节,并促进了更好的关注点分离。使用 ORM 的一个不可避免的副作用是,在查询的最终构建方式、检索多少数据以及成本方面缺乏透明度,这意味着会影响可扩展性和性能。
在构建表示层时,有必要以自动化、面向恢复和不受约束的方式促进横向扩展。在他的文章《高性能网站》中,Google 的 Steve Souders 专注于前端性能。他提供了一份详细的最佳实践清单,其中许多实践除了对延迟的影响外,还使前端更容易横向扩展。
当涉及到用于连接 Web 服务组件的网络时,似乎有无数种方法可以通过使其执行“增值”功能来引入复杂性。现代网络设备具有许多深奥的功能。我们尝试保持网络简单、愚蠢和廉价。
最后,内容交付所经过的互联网路径可能会影响 Web 服务的性能和最终的可扩展性。在他的文章《提高互联网性能》中,Akamai Technologies 的 Tom Leighton 超越了表示层,评估了传输容量、延迟和可靠性如何影响性能,并讨论了避免瓶颈的内容交付方法。
负责构建可扩展 Web 服务的从业人员在短短几年内,其面临的挑战、期望和可用的技术都发生了显著变化。虽然现代 Web 服务比以前的情况要复杂得多,但其中需要从头开始构建的部分却少得多。
TOM KILLALEA 自 1998 年以来一直在 Amazon.com 工作,现任技术副总裁,负责基础设施和分布式系统工程。
最初发表于 Queue 第 6 卷,第 6 期—
在 数字图书馆 中评论本文
Niklas Blum, Serge Lachapelle, Harald Alvestrand - WebRTC - 开放 Web 平台的实时通信
在这个疫情时期,世界比以往任何时候都更依赖于基于互联网的 RTC(实时通信)。在过去十年中,RTC 产品的数量呈爆炸式增长,这在很大程度上是由于更便宜的高速网络接入和更强大的设备,同时也因为一个名为 WebRTC 的开放、免版税的平台。WebRTC 正在从实现有用的体验发展到在疫情期间让数十亿人继续工作和教育,并保持重要的人际交往方面变得至关重要。WebRTC 未来的机遇和影响确实令人着迷。
Benjamin Treynor Sloss, Shylaja Nukala, Vivek Rau - 重要的指标
衡量你的站点可靠性指标,设定正确的目标,并努力准确地衡量这些指标。然后,你会发现你的服务运行得更好,停机时间更少,用户采用率也更高。
Silvia Esparrachiari, Tanya Reilly, Ashleigh Rentz - 跟踪和控制微服务依赖关系
如果你曾将钥匙锁在房子或车里,你就会熟悉依赖循环。没有钥匙你打不开锁,但没有打开锁你就拿不到钥匙。有些循环是显而易见的,但更复杂的依赖循环可能很难在导致中断之前找到。跟踪和控制依赖关系的策略对于维护可靠的系统是必要的。
Diptanu Gon Choudhury, Timothy Perrett - 为互联网规模服务设计集群调度器
希望构建调度系统的工程师应考虑他们使用的底层基础设施的所有故障模式,并考虑调度系统的运营商如何在租户系统所有者进行故障排除期间配置补救策略,同时帮助保持租户系统尽可能稳定。