下载本文的 PDF 版本 PDF

可扩展性的 20 个障碍

注意这些可能阻止 Web 应用程序扩展的陷阱。


Sean Hull,重量级互联网集团


Web 应用程序的增长可能断断续续。客户数量可能会迅速增加,应用程序使用模式可能会因季节而异。这种不可预测性使得应用程序必须是可扩展的。实现可扩展性的最佳方法是什么?

本次调查揭示了 20 个最大的瓶颈,这些瓶颈会降低和减缓可扩展性。通过在您的环境和应用程序中找出这些问题,并消除最严重的罪魁祸首,您将走上超速增长的道路。

扩展性能的 10 个障碍

性能是 Web 可扩展性的关键。如果您增加更多客户,您希望您的应用程序继续以同样快的速度为所有客户提供服务。过多的延迟会导致用户放弃。通过了解所有可能导致应用程序拥塞的方式并避免这些瓶颈,您可以防止应用程序的性能下降。

1. 两阶段提交

通常,当数据库中的数据发生更改时,它会同时写入内存和磁盘。当提交发生时,关系数据库会承诺将数据冻结在真实存储介质上的某个位置。请记住,内存无法在崩溃或重启后幸存。即使数据缓存在内存中,数据库仍然必须将其写入磁盘。MySQL 二进制日志或 Oracle 重做日志符合要求。

使用 MySQL 集群或分布式文件系统(如 DRBD(分布式复制块设备)或 Amazon多可用区 (多可用区)区域),提交不仅发生在本地,而且也发生在远程端。一个两阶段提交意味着等待来自远端的确认。由于网络和其他延迟,这些提交可能会被毫秒级地减慢,就像高速公路上的所有汽车都被重载减慢一样。对于那些考虑使用多可用区或读取副本的人,Amazon RDS(关系数据库服务)用例比较,请访问 http://www.iheavy.com/2012/06/14/rds-or-mysql-ten-use-cases/,这将有所帮助。

同步复制也存在这些问题;因此,MySQL 的解决方案是半同步,这在真正的两阶段提交中做出了一些妥协。

2. 缓存不足

缓存在所有层都非常重要,那么最佳缓存位置在哪里:浏览器、页面、对象还是数据库层?让我们逐步了解这些。

浏览器缓存似乎遥不可及,直到您意识到浏览器从 Web 服务器及其呈现的页面获取指令。因此,如果其中包含的对象具有更长的过期时间,浏览器将缓存它们,并且不需要再次获取它们。这不仅对用户来说更快,而且对于托管网站的服务器来说也更快,因为所有回访者都会减轻负载。

有关浏览器缓存的更多信息,请访问 http://www.iheavy.com/2011/11/01/5-tips-cache-websites-boost-speed/。请务必设置过期标头和缓存控制。

页面缓存需要使用 Varnish 等技术https://www.varnish-cache.org/)。将其视为具有高速和低开销的迷你 Web 服务器。它无法处理像 Apache 那样复杂的页面,但它可以更好地处理非常简单的页面。因此,它位于 Apache 前面并减少负载,允许 Apache 处理更复杂的页面。这就像交通警察让自行车通过路口,然后再全神贯注于更复杂的机动车辆。

对象缓存由 memcache 之类的东西完成。将其视为便利贴应用程序的便签。每次数据库访问首先检查对象缓存以获取当前数据并回答其问题。如果找到所需的数据,它将以快 10 到 100 倍的速度获得结果,从而使其能够更快地构建页面并在眨眼间将所有内容返回给用户。如果它没有找到所需的数据,或者只找到部分数据,那么它将发出数据库请求并将这些结果放入 memcache 中,供以后的会话享用和受益。

3. 磁盘 I/O 速度慢、RAID 5、多租户存储

数据库中的一切,一切,一切都受到存储的限制——不是存储的大小或空间,而是数据写入这些设备的速度。

如果您使用的是物理服务器,请注意 RAID 5,这是一种 RAID(独立磁盘冗余阵列)类型,它使用一个磁盘进行奇偶校验和保护。然而,它会带来巨大的写入惩罚,您必须始终承担。更重要的是,如果您丢失了一个驱动器,这些阵列在重建期间会慢得无法使用。

解决方案是从 RAID 10 开始,它可以让您在镜像集上进行条带化。这样就不会产生奇偶校验计算,也不会在重建期间产生惩罚。

云环境可能与 Amazon EBS(弹性块存储)等技术配合使用,Amazon EBS 是一种类似于存储区域网络的虚拟化磁盘。由于它是基于网络的,您必须与其他租户(又名客户)争夺和竞争读取和写入该存储。此外,这些单独的磁盘阵列只能处理这么多读取和写入,因此您的邻居会影响您的网站和应用程序的响应时间。

最近,亚马逊推出了一项品牌名称糟糕的产品,称为 Provisioned IOPS(每秒 I/O 操作数)。这对于技术人员来说可能听起来像是一个很棒的名字,但对于其他人来说,它没有任何值得注意的含义。尽管如此,它仍然很重要。这意味着您可以锁定并保证数据库渴望的磁盘性能。如果您在 Amazon 上运行数据库,那么一定要看看这个。

4. 串行处理

当顾客在有 10 个收银台开放的杂货店排队结账时,这就是并行工作。如果每个收银员都在午休,只有一个收银台开放,那就是串行化。突然,一条长队形成并蜿蜒穿过商店,不仅让结账的顾客感到沮丧,也让仍在购物的顾客感到沮丧。这种情况发生在桥梁收费站,当开放的车道不够多时,或者在体育场馆,当每个人都在同一时间离开时。

Web 应用程序绝对应该避免串行化。您是否看到备份正在等待 API 调用返回,或者您的所有 Web 节点都在使用一个搜索服务器?您的应用程序形成队列的任何地方都是串行化,应该不惜一切代价避免。

5. 缺少功能标志

开发人员通常为业务部门和客户构建功能和特性。功能标志是操作上的必需品,允许在后端配置文件或管理 UI 页面中打开或关闭这些功能。

为什么它们如此重要?如果您曾在凌晨 4 点救火,那么您就会理解应急计划的必要性。您必须能够禁用应用程序的评分、评论和其他辅助功能,只是为了不让整个应用程序崩溃。更重要的是,随着新功能的推出,有时只有当大量互联网用户访问该站点时,才会出现问题。功能标志允许您禁用一些功能,而无需使整个站点脱机。

6. 数据库的单副本

您应该始终至少有一个在线的读取副本或 MySQL 从库。即使您不使用从库进行浏览——但您也应该这样做,因为您将构建一个仅浏览模式,对吗?

拥有数据库的多个副本意味着横向扩展。一旦您有两个副本,您就会明白三个或四个副本如何使您的基础设施受益。

7. 使用数据库进行排队

MySQL 数据库服务器非常擅长存储表或数据以及它们之间的关系。不幸的是,它不擅长充当应用程序的队列。尽管如此,许多开发人员还是养成了为此目的使用表的习惯。例如,您的应用程序是否有某种作业表,或者可能有一个状态列,其值如“正在处理中”, “在队列中”,和“已完成”?如果是这样,您会在无意中使用表作为队列。

由于锁定挑战以及扫描和轮询过程以查找更多工作,此类解决方案会遇到可扩展性障碍。它们通常会减慢数据库的速度。幸运的是,一些优秀的开源解决方案可用,例如 RabbitMQ(https://rabbitmq.cn/)或 Amazon 的 SQS(简单队列服务;http://aws.amazon.com/sqs/)。

8. 使用数据库进行全文搜索

页面搜索是应用程序被困的另一个领域。虽然 MySQL 已经有了全文索引一段时间了,但它们仅适用于 MyISAM 表,这是一种遗留表类型,它不是防崩溃的,非事务性的,而且对开发人员来说完全是一个全面的麻烦。

一种解决方案是使用专用搜索服务器,例如 Solr(http://lucene.apache.org/solr/)。这些服务器具有适用于您正在使用的任何语言的良好库,并且高速访问搜索。这些节点也具有良好的可扩展性,并且不会拖累您的数据库。

或者,Sphinx SE 是 MySQL 的存储引擎,将 Sphinx 服务器集成到数据库中。如果您着眼于未来,Fulltext 即将推出到 InnoDB,MySQL 的默认存储引擎,在 MySQL 5.6 版本中。

9. 对象关系模型

ORM(对象关系模型)是每个使用过它的 Web 公司的祸根,就像用味精烹饪一样。一旦你开始使用它,就很难戒掉。

优点是 ORM 有助于快速原型设计,并允许不是 SQL 大师的开发人员以对象或内存结构的形式读取和写入数据库。它们更快、更简洁,并提供更快的功能交付——直到您在服务器上推出并想要扩展。

然后您的 DBA(数据库管理员)将带着一个非常运行缓慢的,非常丑陋的查询来到团队,并说:“这在应用程序中的哪个位置?我们需要修复它。需要重写。” 然后您的开发团队会说:“我们不知道!” 运维团队则回以难以置信的目光。

跟踪不良 SQL 并将其根除的能力至关重要。不良 SQL 将会发生,您的 DBA 团队将需要正确地索引。如果查询来自 ORM,它们不利于所有这些。然后您将面临巨大的技术债务和拆卸和更换的挑战。

10. 缺少检测

检测为 Web 应用程序提供速度计和燃油表。您不会在没有它们的情况下开车,对吗?它们公开有关应用程序内部工作原理的信息。它们记录时间并提供有关应用程序大部分时间花费在哪里的反馈。

一个非常流行的 Web 服务解决方案是 New Relic(http://newrelic.com/),它提供对每个人——项目经理、开发人员、运维团队,甚至业务部门都可以查看图表并了解正在发生的事情。

一些开源检测项目也可用。

超越优化速度的 10 个扩展障碍

速度不是唯一会阻碍可扩展性的因素。以下 10 个问题会影响 Web 应用程序维护和构建可扩展性的能力。最佳实践可以避免这些问题。

1. 缺少代码存储库和版本控制

尽管现在很少见,但一些互联网公司仍然尝试在没有版本控制的情况下构建软件。然而,那些使用它的人知道它为团队提供的日常优势和组织控制。

如果您不使用它,随着您的应用程序变得越来越复杂,您将陷入技术债务的螺旋式上升。将不可能添加更多开发人员并处理您的架构和脚手架的不同部分。

一旦您开始使用版本控制,请务必将所有组件都放入其中,包括配置文件和其他必需品。在部署时必须找到和跟踪的缺失部分会成为额外的风险。

2. 单点故障

如果您的数据在单个主数据库上,那就是单点故障。如果您的服务器位于单个磁盘上,那就是单点故障。这只是技术术语中的阿喀琉斯之踵。

必须不惜一切代价根除这些单点故障。问题在于识别它们。即使依赖单个云提供商也可能是单点故障。亚马逊的数据中心或区域故障就是一个例子。如果 AirBNB 有多个提供商或以不同的方式使用亚马逊,那么在 2012 年 10 月 Amazon Web Services 部分宕机时,AirBNB 就不会遇到停机http://www.iheavy.com/2012/10/23/airbnb-didnt-have-to-fail/)。

3. 缺少仅浏览模式

如果您曾经在深夜尝试在 Yelp、Facebook 或 Tumblr 上发表评论,您可能会收到一条消息,内容大致为:“此功能不可用。请稍后再试。” “稍后”可能是五分钟或 60 分钟。或者,您可能正在尝试预订机票,并且必须重试几次。对于非技术用户来说,该站点似乎仍然运行正常,但只是有这种奇怪的小故障。

这里发生的事情是应用程序允许您浏览该站点,但不进行任何更改。这意味着主数据库或某些存储组件已脱机。

仅浏览模式是通过保留主数据库的多个只读副本来实现的,使用诸如 MySQL 复制或 Amazon 读取副本之类的方法。由于应用程序几乎完全在浏览模式下运行,因此它可以访问这些数据库,而无需主数据库。这是一个巨大的胜利。

4. 沟通不畅

在讨论可扩展性时,沟通似乎是一个奇怪的地方,但 Web 应用程序的技术层无法与团队驾驭的社交和文化层分开。

强大的沟通渠道是必要的,团队成员必须知道在遇到麻烦时该向谁求助。良好的沟通需要自信且知识渊博的领导,以及倾听和改进的开放态度。

5. 缺少文档

文档发生在 Web 应用程序的许多层。开发人员需要记录程序、函数和页面,以便为未来查看该代码的人提供提示和见解。运维团队需要在配置文件中添加注释,以便在出现问题时提供更改历史记录和见解。业务流程和关系应该并且可以记录在公司 Wiki 中,以帮助人们找到自己问题的解决方案。

文档在各个层面都有帮助,是每个人都应该接受的习惯。

6. 缺少消防演习

消防演习总是被推到次要位置。团队可能会说:“我们有备份;我们有保障。” 没错,直到他们尝试恢复这些备份并发现它们不完整,缺少一些配置文件或关键数据片段。如果这种情况发生在您正在扑灭真正的火灾时,那么您不希望发生的事情将会打击到办公室的风扇。

消防演习允许团队在真正需要之前演练动作。您的公司应该安排其运维团队的一部分每年进行几次完整应用程序的恢复。借助 AWS 和云服务器,这比以前容易得多。启动服务器以证明您的所有组件都已备份是一个好主意。在此过程中,您将了解需要多长时间、困难的步骤在哪里以及需要注意什么。

7. 监控和指标不足

监控与版本控制属于同一类最佳实践:它应该非常基本,以至于您无法想象没有它工作;然而,有些 Web 商店没有监控,或者监控不足——某些服务器或关键组件被遗漏。

随着时间的推移收集系统和服务器级别数据,以及应用程序和业务级别的可用性,同样重要。如果您不想自己开发,请考虑使用 Web 服务解决方案为您的企业提供真正的正常运行时间。

8. 个人英雄主义式运维

您骑着快马冲进小镇,带着枪走进酒吧,您认为您会交到朋友吗?不,您只会吓唬所有人屈服,但没有真正的忠诚度。那是因为您可能会像修复问题一样频繁地破坏东西。自信固然重要,但最好与团队合作。团队的智慧大于任何个人。

团队需要沟通他们正在更改的内容,以受控的方式进行更改,计划任何中断等等。谨慎和规避风险才能取得胜利。始终要有 B 计划。您应该能够撤消您刚刚所做的更改,并意识到哪些命令是破坏性的,哪些命令是无法撤消的。

9. 不断增长的技术债务

随着应用程序多年来的发展,团队可能会花费越来越多的时间来维护和支持旧代码、消除错误或消除缺陷。因此,他们花在新功能上的时间更少。必须密切管理用于偿还债务与真正的新功能之间的这种时间平衡。如果您发现您的技术债务正在增加,那么可能是时候咬紧牙关并重写了。重写将占用新功能和客户功能的直接业务利益的时间,但从长远来看是最好的。

技术债务并不总是容易识别或关注。当您构建功能或消除错误时,您会更专注于近距离级别的细节。很容易只见树木不见森林。这就是为什么通才更擅长扩展 Web(http://www.iheavy.com/2011/10/25/why-generalists-better-scaling-web/)。

10. 日志记录不足

日志记录与指标和监控密切相关。您可能会在排除故障和调试时启用更多日志记录,但在持续的基础上,您将需要它用于关键的基本服务。服务器系统日志、Apache 和 MySQL 日志、缓存日志等都应该正常工作。如果日志记录过多,您可以随时减少日志记录,或者修剪和轮换日志文件,丢弃旧文件。

结论

这 20 个障碍会影响可扩展性并降低 Web 应用程序的性能。通过避免这些障碍并遵循此处概述的做法,Web 应用程序开发人员将能够最大限度地减少延迟并保证他们的应用程序可以根据需要进行扩展。

喜欢还是讨厌?请告诉我们
[email protected]

Sean Hull 是纽约重量级互联网集团的创始人兼高级顾问。他拥有超过二十年的技术顾问、顾问、作家、演讲者和企业家的经验,曾与 AppNexus、The Hollywood Reporter、Billboard、NBC Universal、Zagats、Rent the Runway 和 ideeli 等客户合作。这些超速增长公司每月处理多达 1 亿独立访客。如此巨大的流量带来了网站可扩展性、业务连续性、安全性以及架构挑战。Hull 的专长包括 MySQL 和 Linux 性能以及 Amazon EC2 部署。可以通过 [email protected] 或 Scalable Startups 博客联系他:http://www.iheavy.com/blog/

© 2013 1542-7730/13/0700 $10.00

acmqueue

最初发表于 Queue vol. 11, no. 7
数字图书馆 中评论本文





更多相关文章

Shylaja Nukala, Vivek Rau - 为什么 SRE 文档很重要
SRE(站点可靠性工程)是一项工作职能、一种思维模式以及一套工程方法,用于使 Web 产品和服务可靠地运行。SRE 在软件开发和系统工程的交叉点运行,以解决运营问题并设计解决方案,以可扩展、可靠和高效地设计、构建和运行大规模分布式系统。成熟的 SRE 团队可能拥有与许多 SRE 功能相关的完善的文档体系。


Taylor Savage - Web 组件化
如今,在软件工程中,没有比 Web 开发更艰巨的任务了。Web 应用程序的典型规范可能如下所示:该应用程序必须跨各种浏览器工作。它必须以 60 fps 的速度运行动画。它必须立即响应触摸。它必须符合特定的一组设计原则和规范。它必须在几乎所有可以想象到的屏幕尺寸上工作,从电视和 30 英寸显示器到手机和手表表面。它必须在长期内得到良好的工程设计和可维护性。


Arie van Deursen - 超越页面对象:使用状态对象测试 Web 应用程序
Web 应用程序的端到端测试通常涉及使用 Selenium WebDriver 等框架与网页进行棘手的交互。隐藏此类网页复杂性的推荐方法是使用页面对象,但首先要回答一些问题:在测试 Web 应用程序时,应该创建哪些页面对象?页面对象中应该包含哪些操作?给定您的页面对象,您应该指定哪些测试场景?


Rich Harris - 消除准入门槛
Web 开发领域正在进行一场战争。一方是工具制造者和工具用户的先锋,他们以破坏糟糕的旧观念(在这种环境中,“旧”意味着任何一个月前在 Hacker News 上首次亮相的东西)以及关于转译器等的热烈辩论而蓬勃发展。





© 保留所有权利。

© . All rights reserved.