- 浏览: 305806 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
完善自我:
支持一下!
揭秘IT人才特点:中美印日四国程序员比较 -
悲剧了:
好文,看玩thinking in java的提到的异常处理,看 ...
高效的Java异常处理框架(转) -
yin_bp:
开源框架bbossgroups页支持组件异步方法调用哦,详情请 ...
Spring 3中异步方法调用 -
flyjava:
sun的悲哀
Apache怒了,威胁说要离开JCP
引言
在扩展大量大型的分布式系统期间,我有机会观察(并实践)了一些最差实践。这些最差实践中的大部分在开始时都没有危害,但如果疏忽大意,它们就会对系统的发展和可伸缩性构成危害。很多文章都聚焦于最佳实践,以确保拥有一个易于维护和可伸缩的系统,但在本文中,我主要强调的则是一些应该规避的最差实践。
技术
没有任何一种技术或架构能实现所有的需求。了解何时该反思现有的方法、如何拓宽视野以超越局部范围、或如何进行依赖的有效控制,这些都是可伸缩性的关键特性。
让我们进一步分别研究一下。
金锤子
金锤子起源于一条古老的谚语:如果你只有一把锤子,那么任何东西在你眼里都是一枚钉子
。很多开发人员都局限在仅使用一种技术的观念中——其代价是不得不使用选定的技术来构建和维护基础设施,即便已经存在另一种技术更适用于特定问题域的功能和抽象。强行把一种技术用在它所不擅长的方面,有时会适得其反
。
举例来说,持久化键—值对问题的常见解决方案是使用数据库。之所以常常这样选择是因为组织或开发者有坚实的数据库实践,针对许多问题自然而然就会沿用同样的解决途径。当数据库的特性(关系完整性、锁、连接和方案)成为瓶颈或阻碍了其伸缩扩展时,问题也就出现了。这是因为应用基于数据库的解决方案要发展,其成本通常要比使用其它可用技术更为昂贵。随着键—值存储访问率的增加,数据库并发模式的性能就开始降低,而数据库具备的高级特性却被闲置。许多传统关系数据库的替代方案都是针对这些缺点的,比如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
)
发表评论
-
Qi4j和NoSql运动
2010-11-16 23:00 156524日一篇Qi4j and the NoSQL ... -
Threaded vs Evented Servers
2010-11-16 22:48 898Threaded vs Evented Servers ... -
BASE: An Acid Alternative
2010-11-16 21:13 935In partitioned databases, tra ... -
eBay 的Scalability最佳实践
2010-11-16 20:52 883用什么来衡量一天没 ... -
Scalability Best Practices: Lessons from eBay
2010-11-16 20:45 820At eBay, one of the primary a ... -
SmugMug 的架构介绍
2010-11-16 20:36 850本文介绍的 SmugMug 是一家提供付费图片 ... -
来自淘宝的架构经验
2010-11-16 18:07 1204日前参加了一场淘宝网 架构师黄裳带来的技术分享,在最后他 ... -
可伸缩性最佳实战
2010-11-16 17:50 560异步 同步调用使得组件和组件之间紧密耦合起来,这样就使得 ... -
伸缩性和可用性反模式
2010-11-16 17:48 685这篇文章讲了伸缩性 和可用性方面的反模式,也按照自己的理 ... -
使用qi4j实现DCI架构
2010-11-16 17:24 2888我曾经DCI架构是什么? 在一文中提到Qi4j框架实现DCI ... -
DCI架构是什么?
2010-11-16 17:07 1990DCI是数据Data 场景Context 交互Interact ... -
纵向扩容 vs. 横向扩容
2010-11-02 09:58 5384该文原版著作权属于Malc ... -
云计算在电信应用中的思考
2010-11-01 17:59 908云计算是在网格(Grid)、效用(Utility)和 ... -
真正的线性可伸缩性需要新的模式和中间件架构吗?
2010-11-01 17:27 925在构建线性可收缩应用 ... -
性能与可伸缩性的概念及其关键影响因素
2010-11-01 17:22 1087性能与可伸缩性常常决定企业应用的成败,尤其在 ... -
构建的可伸缩性和达到的性能
2010-11-01 17:19 948实现伸缩性和性能调优的经验所保有的价值容易被低估。两者都是“晚 ... -
可伸缩性,美妙的可伸缩性
2010-11-01 16:37 1390可伸缩性带来的好处 ... -
大型门户网站架构设计的可伸缩性
2010-11-01 16:34 863我们知道,对于一个大型门户网站来说,可伸缩性是非常重要的,怎么 ... -
可伸缩性设计
2010-11-01 16:27 969好的设计是实现高度可 ... -
为性能和可伸缩性做架构和设计上的Review
2010-11-01 16:05 844部署和体系结构 ...
相关推荐
VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB.NET可伸缩性技术手册VB...
可伸缩性最佳实践:来自eBay的经验
分布式系统可伸缩性研究综述_陈斌.pdf
资源名称:数据访问宝典-实现最优性能可伸缩性的数据库应用程序内容简介:在当今的企业数据库应用程序中,性能和可伸缩性比过去任何时候更为关键,传统的数据库调整对于解决可能在这些应用程序中遇到的性能问题有些...
本代码实现了对MPEG2 SNR可伸缩性编码,可以作为理解SNR可伸缩性编码的入门。
本书包含:构建和开发应用程序,以便它们易于扩展。 了解不同的缩放和分区选项以及组合。 学习加快响应速度的技巧。 深入研究缓存,列族...有效平衡可扩展性,性能,响应能力和可用性,同时最大限度地减少停机时间。
本文将讲述几项技术,这些技术可用于提高基于 SQL Server的应用程序的性能或改善其可伸缩性。将仔细说明 LEFT JOIN、CROSS JOIN 的使用以及IDENTITY 值的检索。调整您的数据库及其查询需要占用时间、进行分析,还...
全书共分6章和2个附录,讲述了可伸缩性的规划、数据层、中间层、表示层,以及可伸缩性的测量等内容。 本书内容切合实际,适合希望了解如何开发可伸缩的企业级的应用程序的VB.NET程序员阅读。 本书英文原名为:...
全书共分6章和2个附录,讲述了可伸缩性的规划、数据层、中间层、表示层,以及可伸缩性的测量等内容。 本书内容切合实际,适合希望了解如何开发可伸缩的企业级的应用程序的VB.NET程序员阅读。 本书英文原名为:...
构建一个可伸缩性的容器平台的挑战与机遇
很不错的几个windows可可伸缩性范例,让你受益匪浅!
基于H264的精细可伸缩性视频编码研究基于H264的精细可伸缩性视频编码研究
本代码实现了对MPEG2 空间可伸缩性的基本方法,对于深入理解这一可伸缩性有较大效果
渐进、精细的可伸缩性视频编码渐进、精细的可伸缩性视频编码
基于对象的精细可伸缩性编码基于对象的精细可伸缩性编码
PHP实例开发源码—Wikka高速可伸缩性软件.zip PHP实例开发源码—Wikka高速可伸缩性软件.zip PHP实例开发源码—Wikka高速可伸缩性软件.zip
JPEG2000系统在图像传输中提供了有关质量,分辨率和颜色成分的可伸缩性。 但是,仍然缺乏关于语义内容的可伸缩性。 我们在JPEG2000编解码器中提出了一种生物学上合理的基于显着区域的位分配机制,目的是增强语义内容...
SQL Server 2008 数据仓库可伸缩性相关功能介绍 白皮书