`

可伸缩性的最差实践

阅读更多

引言
在扩展大量大型的分布式系统期间,我有机会观察(并实践)了一些最差实践。这些最差实践中的大部分在开始时都没有危害,但如果疏忽大意,它们就会对系统的发展和可伸缩性构成危害。很多文章都聚焦于最佳实践,以确保拥有一个易于维护和可伸缩的系统,但在本文中,我主要强调的则是一些应该规避的最差实践。
技术
没有任何一种技术或架构能实现所有的需求。了解何时该反思现有的方法、如何拓宽视野以超越局部范围、或如何进行依赖的有效控制,这些都是可伸缩性的关键特性。 让我们进一步分别研究一下。
金锤子
金锤子起源于一条古老的谚语:如果你只有一把锤子,那么任何东西在你眼里都是一枚钉子 。很多开发人员都局限在仅使用一种技术的观念中——其代价是不得不使用选定的技术来构建和维护基础设施,即便已经存在另一种技术更适用于特定问题域的功能和抽象。强行把一种技术用在它所不擅长的方面,有时会适得其反
举例来说,持久化键—值对问题的常见解决方案是使用数据库。之所以常常这样选择是因为组织或开发者有坚实的数据库实践,针对许多问题自然而然就会沿用同样的解决途径。当数据库的特性(关系完整性、锁、连接和方案)成为瓶颈或阻碍了其伸缩扩展时,问题也就出现了。这是因为应用基于数据库的解决方案要发展,其成本通常要比使用其它可用技术更为昂贵。随着键—值存储访问率的增加,数据库并发模式的性能就开始降低,而数据库具备的高级特性却被闲置。许多传统关系数据库的替代方案都是针对这些缺点的,比如CouchDB、SimpleDB或BigTable
另一个常见的“锤子”就是总利用线程来进行并发编程 。尽管线程确实是针对并发的,但它们也带来了成本,这些成本包括代码复杂性的增加、以及由于目前线程的的锁定和访问模型造成的组件编排(composability )方面的固有不足。由于如今最流行的编程语言都使用线程处理并发,因此数千行代码都含有竞态条件、潜在的死锁和不一致的数据访问管理。有些正在成长的社区提出了另一些并发方案,这些方案不存在线程的可伸缩性问题,也就是由Erlang或Stackless Python提倡的并发模型 。即便不在实际生产中选择那些语言,研究一下它们的概念(比如消息传递或异步I/O )仍然是一种不错的实践。
资源滥用
小范围的问题开发者们一般都能处理得得心应手:使用分析工具、了解算法的空间和时间复杂度、或者了解哪种场合应该用哪种列表实现。但并非每个人都善于认识到大型系统的约束条件,比如识别共享资源的性能要求、了解服务的各种客户、或发掘数据库的访问模式
应用程序实现伸缩性的普遍方法是不断横向部署冗余的、无状态的、彼此不共享内容的服务,以此作为最理想的体系架构 。但以我的经验看来,这种扩展往往会忽视新增服务对共享资源的影响
比如说,如果一个特定的服务使用数据库作为持久存储,它通常通过一个线程池来管理数据库连接。使用池是不错的方法,有助于避免进行过多的数据库连接处理。然而数据库仍然是共享资源,除了单个池配置,还必须对所有池从总体上进行管理。下面两个实践就会导致失败:
1,持续增加服务数,但并不减小池的最大数。
2,增大单个池的大小,而不减小服务数量。

以上两种情况中,除了按性能要求配置应用之外,连接的总数也必须加以管理 。此外,还要持续监控数据库的容量,以保持连接均衡
处理共享资源的可用性至关重要,准确的说,这是因为它们一旦失效,由于其“共享”的本质,失效会对系统造成全面的影响,而非孤立存在
大泥球
依赖是很多系统讨厌却又必不可少的东西,不积极地处理好依赖及其版本会损害灵活性和可伸缩性
代码的依赖管理 有多种不同的模式:
1,同时编译整个代码集
2,基于已知版本选取构件和服务
3,发布的模型和服务所有变更都向后兼容
让我们看看这些情形。首先,在大泥球模式下,整个系统作为一个单元编译和部署。这种模式拥有明显的优势,也就是将依赖管理交给编译器处理,并能提前捕获一些问题,但它会因每次都部署整个系统(包括测试、交付和大范围变化引起的风险)而引发可伸缩性的问题 。在这种模式下,会更难隔离系统的变化
在第二种模式中,依赖都是按需挑选的,但是变化经过依赖传递之后依旧出现第一种模式一样的难题
第三种模式中,服务负责依赖的版本化,并向客户端提供向后兼容的接口 。这明显减轻了客户端的负担,从而允许逐步升级到新的模型和服务接口。此外,当数据需要转换的时候,它是依靠服务而不是客户端完成的——这进一步稳固了隔离性 。向后兼容的变更意味着打补丁、升级和回滚都不能干扰客户端操作。
采用变更能向后兼容的服务体系架构在最大程度上避免了依赖问题 。它同时方便了在受控环境下进行独立测试,隔离了客户端和版本化数据的变化 。这三个优点对隔离变化来说都很重要。最近发布的Google Protocol Buffers项目 也在倡导向后兼容的服务模型和接口。
全部打包还是部分打包
处理依赖时要考虑的另一件事情是如何对应用内容打包。
在一些场景中,比如Amazon Machine Images或Google AppEngine应用,它们的整个应用和所有的依赖都一起打包发布。这种囊括一切的打包方法保持了应用的自包含,但它增加了包的总大小,而且应用中任何地方的一个小小改变,都会迫使系统重新部署整个应用包(甚至对同一台物理机器上许多应用使用的共享库也是如此)。
替代方案是将应用的依赖移出主机系统,令应用包只包含依赖图的若干部分 。这控制了包的大小,但由于应用在能提供服务之前需要将特定的组件传递到每台机器上,所以增加了部署配置。依赖项目没有立即准备好、机器没有经常测试、抑或是依赖错误,由于以上种种,不将整个包部署为自包含的方式会制约将应用部署到异构的、非标准化的机器上
后一种方案——分成不同范围(全局的、机器的、应用的)去处理依赖——必然会增加疏漏和复杂性 。它减少了配置和依赖隔离,增加了操作的复杂性。一般而言,隔离能增加可伸缩性 ,所以尽可能选用囊括一切的方法,除非有例外情况。
无论在代码还是在依赖处理中,最差实践就是不清楚模块间的关系,没有规划好模块以便于对其进行管理。未能增强控制是可伸缩性的一大绊脚石
忘记检查时间
在分布式系统中,通常的目标是尽可能地将开发者和负责分布式调用的复杂方法隔离开来。这使主要的开发工作集中于核心的业务逻辑上,而不用担心失效恢复、超时以及其它分布式系统必需的需求。但是,让远程调用看起来像本地调用一样就意味着开发者要像本地调用一样编码。
我常发现很多代码都期望所有的远程请求能及时完成,但这样的期望是不合理的。比如说,Java在JDK1.5中仅为HTTPURLConnection 类引入了读超时 ,而让开发者要么创建线程去杀死进程,要么天真地等待响应。
Java中,另一个潜在的时间处理不合理的例子是DNS查找 。在一个长时间运行的典型系统中,执行完最初的DNS查找之后,如果不进行明确的配置,结果会缓存在JVM的生命期内。如果外部系统更改了主机的IP地址,将不能正确处理该条目,而且在很多情况下,因为编程时没有设置连接超时时间,连接就会被挂起。
为了对系统进行合适的伸缩扩展,为请求处理分配好时间是极其重要的。 有很多方法可以实现,有一些是语言内置的(像Erlang),其它的则作为库的形式提供,比如libevent或Java的NIO。抛开实现语言或架构不谈,正确地管理操作等待时间是非常必要的
运行时
建立一个符合成本效益的可扩展方案、处理好依赖、预先考虑到失效都是创建优秀架构的各方面要求。而在生产环境中,系统易于部署和运维的能力也同等重要。 这里同样有很多不利于系统可伸缩性的最差实践。
英雄模式
运维问题普遍的解决方案是有一个“英雄”(关键性人物),他能处理、并经常处理大部分的操作需求。在小规模环境中,当某个人有天赋和能力熟悉整个系统(包括保持系统正常运行的许多细节之处),英雄模式可以正常运行。尽管这是最常见的实施方案之一,但对拥有许多组件的大型系统而言,这种方法就不能进行伸缩扩展了。
在没有形式说明的情况下,“英雄”往往要理解服务依赖,牢记如何开、关特性,或了解其他人已经遗忘了的系统 。“英雄”虽然至关重要,但他不应该是一个个体。
我认为英雄模式最好的解决方案是自动化 。如果组织的情况允许,让个人在团队之间轮换也有帮助 。在银行里,休假有时是强制性的,好让“你这里不行,要到我的机器上做”之类的问题及时暴露出来。
非自动化
系统过度依赖于人工干预往往是存在“英雄”的后果,这面临着可重复生产能力的问题和“英雄”出现意外情况带来的问题。能重现特定的构建、部署和环境很重要,而明确定义的元数据控制下的自动化是实现可重复能力的成功关键
在一些开源项目中,工件的发布过程依赖于个体开发者在自己工作站上构建工件,没有任何措施保证产生出来的工件版本能实际对应到源码控制系统中的某个分支。在这些情况下,完全有可能发布软件,其代码从未被提交到源码控制系统。
综上所述,“英雄”的活动应该由自动化取代,从而确保个人(或许多人)可以相对容易地替换其他人 。自动化的替代方案是增加流程——Clay Shirky为流程给出了一个有趣的定义:流程是对先前蠢行的内在反应 。先前的蠢行在所难免——自动化应该吸取教训。
监控
当时间紧迫时,监控(比如测试)往往是第一个牺牲的环节。有时,在我问及有关组件的运行时表现方面的细节问题时,总没有答案。缺乏对运行系统内部的深入了解和迅速切入问题的能力,不利于对从哪里入手和着手做什么做出正确攸关的决策。
Orbitz很幸运地拥有久经考验的监控软件,它们既能提供服务调用的细粒度详细信息,也能精确显现出问题域的数据。来自监控基础设施的可用度量数据有利于快速有效地解决问题
总结
在不久前Amazon的S3出现服务中断之后,Jeff Bezos说道:遇到问题的时候,我们知道直接原因,我们从那里入手分析并找到了根本原因,然后从根本上进行了修复,又向前迈进了一步。
软件和系统的开发是一个迭代的过程,在这个过程中,失败和成功的机会并存。简单但较难伸缩的解决方案有其一席之地,特别是计划或应用尚处于不成熟的阶段。“好”和“完美”不是对立的。但随着系统的日臻完善,应该除去其中的那些最差实践,这样,成功也就是理所当然的了
非常感谢Monika Szymanski对本文初稿提出的建议。
关于作者
Brian Zimmer是旅游业新创企业Yapta的架构师,是一位受人尊敬的开源社区成员,也是Python软件基金会的成员。他之前作为高级架构师服务于Orbitz。他的博客在http://bzimmer.ziclix.com
查看英文原文:Scalability Worst Practices(http://www.infoq.com/articles/scalability-worst-practices

分享到:
评论

相关推荐

    分布式系统可伸缩性研究综述_陈斌.pdf

    陈斌等人的研究综述对分布式系统可伸缩性的关键概念、实践方法和未来挑战进行了全面而深入的探讨,为系统设计者和优化工程师提供了宝贵的指导。 分布式系统的可伸缩性可以通过物理资源的增加来实现,比如通过增加更...

    VB.NET可伸缩性技术手册

    VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB...

    可伸缩性最佳实践:来自eBay的经验

    可伸缩性最佳实践:来自eBay的经验

    深入比较MySQL与Oracle:性能、可伸缩性与最佳实践

    本文将深入探讨MySQL与Oracle在性能、可伸缩性以及最佳实践方面的比较,并通过代码示例来展示它们在实际应用中的表现。 MySQL和Oracle在性能和可伸缩性方面各有优势。Oracle适合大型企业和数据密集型应用,而MySQL...

    数据访问宝典-实现最优性能可伸缩性的数据库应用程序

    资源名称:数据访问宝典-实现最优性能可伸缩性的数据库应用程序内容简介:在当今的企业数据库应用程序中,性能和可伸缩性比过去任何时候更为关键,传统的数据库调整对于解决可能在这些应用程序中遇到的性能问题有些...

    windows可伸缩性范例

    在IT领域,尤其是在系统管理和架构设计中,"可伸缩性"是一个至关重要的概念。Windows操作系统作为广泛应用的桌面和服务器平台,同样面临着如何提供高效、灵活的可伸缩性解决方案的挑战。本篇将深入探讨"Windows可...

    MPEG2 SNR可伸缩编码

    本代码实现了对MPEG2 SNR可伸缩性编码,可以作为理解SNR可伸缩性编码的入门。

    分布式系统可伸缩性研究综述.pdf

    可伸缩性是衡量分布式系统是否能随着需求和资源的变化而持续满足性能需求的能力。在计算机科学中,特别是在分布式系统领域,可伸缩性的概念至关重要。由于业务需求和技术环境的变化,分布式系统必须能够扩展其处理...

    VB.NET可伸缩性技术手册(下)

    全书共分6章和2个附录,讲述了可伸缩性的规划、数据层、中间层、表示层,以及可伸缩性的测量等内容。 本书内容切合实际,适合希望了解如何开发可伸缩的企业级的应用程序的VB.NET程序员阅读。  本书英文原名为:...

    VB.NET可伸缩性技术手册(上)

    全书共分6章和2个附录,讲述了可伸缩性的规划、数据层、中间层、表示层,以及可伸缩性的测量等内容。 本书内容切合实际,适合希望了解如何开发可伸缩的企业级的应用程序的VB.NET程序员阅读。  本书英文原名为:...

    数据库课程设计中的可伸缩性设计:策略与实践

    通过上述策略和实践,可以在数据库课程设计中实现有效的可伸缩性设计,从而确保数据库系统能够适应未来数据增长和用户增加的需求。记住,可伸缩性设计是一个持续的过程,需要不断地评估和调整以满足不断变化的业务...

    可伸缩网络服务可伸缩网络服务可伸缩网络服务博士论文

    这部分内容可能包含各种网络服务(如CDN内容分发网络、云数据库、API网关等)的可伸缩性优化实践。 “第五章”则可能对整个研究进行总结和展望,提出未来的研究方向和挑战,例如如何更好地预测和控制服务的伸缩行为...

    利用USL预测MySQL数据库可伸缩性.pptx

    《利用USL预测MySQL数据库可伸缩性》 在信息技术领域,数据库的可伸缩性是衡量系统性能的关键指标之一,它关乎到系统能否在工作量增加时保持稳定的服务水平。本文将深入探讨如何利用Universal Scalability Law(USL...

    构建一个可伸缩性的容器平台的挑战与机遇

    在IT行业中,构建一个可伸缩性的容器平台是现代企业数字化转型的关键步骤。这涉及到将应用程序和服务部署在轻量级容器内,通过自动化工具进行管理和扩展,以应对不断变化的业务需求。本文将深入探讨构建这样的平台所...

    行业分类-设备装置-应用于幕墙上的具有可伸缩性的主钢结构.zip

    总的来说,应用于幕墙上的具有可伸缩性的主钢结构是现代建筑技术创新的体现,它融合了结构力学、材料科学和工程实践,旨在提供更安全、更节能且更具适应性的建筑解决方案。随着科技的发展,我们期待更多类似的创新...

    MPEG2 空间可伸缩性编码

    本代码实现了对MPEG2 空间可伸缩性的基本方法,对于深入理解这一可伸缩性有较大效果

Global site tag (gtag.js) - Google Analytics