构建的可伸缩性和达到的性能:一个虚拟座谈会

实现伸缩性和性能调优的经验所保有的价值容易被低估。两者都是“晚些时候”或“我们真正流行起来时”所面临的难题。早期创业公司确实不应该立即花这份钱,而大公司通常不能做出足够快速的反应以实现所需的改变。再加上这需要一个多学科的团队,它立刻就变成了一个需要解决的政治上和工程上的难题。

但是它从来不会从我们的视线中消失——在过去的少数几个 Qcon 会议上,“Architectures You've Always Wondered About(你始终感到惊讶的架构)”专题被淹没了,正因为如此,我们渴望学习“大人物”们如何去做这些事情的技巧和诀窍。

在这次 InfoQ.com 的虚拟座谈会上,我们从几个最大的公司和项目中邀请了几个在实现可伸缩性和性能方面的专家,让我们进入他们取得了成果而我们却依然梦想的神秘世界吧。

座谈会的参与者包括有 Blaine Cook,Twitter 的前任架构师,他领导开发者进行了 Starling 消息队列 ruby gem 的开发。Blaine 在“如何让 Ruby 和 Rails 伸缩自如”的会谈中发出了积极的声音,在这一领域有非常多的经验。

他是被 Randy Shoup 加入的,Randy Shoup 是 eBay 市场架构小组的一个分布式架构师。从 2004 年起,他一直是 eBay 搜索基础架构的主要架构师。而 Matt Youill,则是 Betfair 的首席技术专家。在超过 6 年的时间里,他引领了许多 Betfair 的技术架构。最近他又与 Betfair 的高级技术小组转向一个更长期的高级项目——包括了 Flywheel 技术及其他技术的策略、研究和特殊项目。

为了让与会者来源更多样,我们请专业开发 Rails 性能工具的 FiveRuns 也参加进来。他们派了整个工程团队用了一个下午来商讨其答案——简直可以另外开一个座谈会了。

问题 1:许多人把性能和技术混为一谈。你们怎么回应这种误解呢?

Randy: 我同意独立于任何特定语言或框架来讨论伸缩性问题确实很有价值——不管实现策略如何,模式都是一样的。可是,首先让我们确保自己已经把性能和可伸缩性区分开了。性能是服务于一个单独请求时的资源使用问题。可伸缩性是当要服务更多(或更大)请求时资源消费量如何随之增长的问题。

它们是相关的,但是不是同一件事情:-)。幸运的是,许多改善其中一个问题的方法通常也会改善另一个问题。但是,速度非常快的系统可能并不是最具伸缩性的系统,反之亦然。

FiveRuns: 我们关心性能、可伸缩性、可用性的对比。我们把性能定义为一个操作(或一些操作)如何快速地完成,比如,响应时间、每秒事件处理的数量等等;而可伸缩性——就是应用怎样很好地按比例扩大规模以应对更大的使用需求(比如,用户数、请求速度、数据容量)。

问题 2:当你碰到性能瓶颈时,你如何开始调查是什么导致了这一问题?

Matt: 每个问题都是不同的,但是我想这通常是一个搜集观测资料(即,与许多人进行交谈)并缩小问题范围的过程——通过检查什么仍在继续执行,你可以分离出不再执行的东西。

有两个重要的事情要谨记在心。确保它确实是问题的瓶颈所在。例如,忧虑处理器使用效率低下的问题与一个受 IO 束缚的应用可能没什么关系。从产品环境去进行观测非常重要,不要在阶段环境或开发环境亦或是其他环境上进行观测。试图在“假”的环境里再现问题并收集信息将只能产生“ 假”的结果。

Blaine: 直觉(快速但不可靠,而且容易产生错误)和监测(需要预先的工作,但是这能让你随心所欲地分析问题)。人们经常谈论测试驱动开发,但是可伸缩性需要测量驱动(metric-driven)开发。

像 JMeter 和 Tsung 这样的工具,可以让你模拟负载,但是接受任何事情都要有所保留。如果你有很长的时间(到底多长时间取决于你的流程和构建测试的人)去构建非常周到的测试,你可以获得更好的一手资料。但是,不可能做到和真正的流量一样逼真。

Randy: 通常我们会从注意到问题的地方开始,然后向前追溯。在应用栈的所有层次所进行的监测 / 勘测得越多,就越容易这样做。它还可以帮助有各种学科专长团队里的人们来检查这个问题。

问题 3:当处理 Web 应用的问题时,你发现什么工具最有用?

FiveRuns: 在浏览器层,firebug 是我们所选的工具,因为它提供了对用户执行单页面的感觉的一些深入观察。我们还喜欢 ab & httperf,它给我们提供了一些自动化的负载测试,因此对比于我们从 firebug 中获得页面级的计时,使用这个工具可以获得会话级的计时。

Matt: 我们混合使用成品工具和定制工具。成品工具是非常好的,但是成品意味着它们是通用的。它们没有你应用程序中非常重要的特定标准的知识。例如,在 Betfair 的 Web 应用上下文里,这可能与请求频度和含有相应业务事件(就像足球比赛中的射门、进球)的特殊页面类型相关。通用工具没有“足球比赛”选项。

Blaine: Ganglia 是非常优秀的。同时 Nagios 或 Zabbix(举个例子)将告诉你何时资料遭到破坏,使用少量加工你就能够让 ganglia 给你提供任何东西。对于 MySQL,Innotop + slow query log 帮了大忙。使用 mysql 微妙级日志补丁来察看所有查询中哪些查询的时间在 1 毫秒到 1 秒之间。

Randy: 我非常同意使用日志——我们可以支配的最有用的工具是我们的监测框架,我们的应用服务器使用它来记录我们所做的各个操作的调用 / 事务发生时间——整个 URL 的执行情况、嵌套的数据库访问、嵌套的服务调用等等。这就让我们能够远程诊断大多数产品问题,而不需要在任何地方都配备调试器。我们还保留了这些日志的可查询历史,我们可以用之比较以前和当前的性能,以及随时间推移的趋势。

问题 4:当你有一个堆栈(或核心)问题需要诊断时,什么工具可以提供帮助?

Randy: GDB 和 DTrace 是用于 C++ 的基础架构。core 或 pstack 是个颇有价值的工具。对于 Java,我们使用了 tracing 和各种 Java 调试器,它们组成了 eBay 基础架构的主要部分。可是,调试器不应当是你用的第一个工具;它应该是你用的最后一个工具。产品代码需要用足够多的仪器来远程诊断问题。

Matt: 我们有许多魔法!我们使用各种工具来重现问题并调试它们(包括栈的问题)——Visual Studio、 Eclipse、WinDbg、cdb、Purify、Fortify、dtrace 以及许多定制的东西,为我们的架构所构建的东西。

问题 5:你认为像 Yahoo! 性能前十名等等这样的文章有用吗?领域或应用的可伸缩是个问题吗?

Blaine: 这两者的答案都是肯定。从某点上讲,伸缩性已经从领域问题(即,如果你不使用内存缓存或者一个等价的分布式哈希表和基于内存的缓存)转移了,而你仍然处于“领域”范围。一些应用充分地理解了这一点。当今静态内容的可伸缩性已不那么重要了,那只是花钱的问题并需要公司有好的社会组织的问题。

FiveRuns: 我们认为像 Yahoo! 性能文章这样的资源是有用的。我们认为把应用架构与问题领域进行匹配是非常关键的——实际上,我们对问题领域的所有假设都定义了软件系统质量方面的约束。

换句话说,我们都期望问题领域可以定义针对性能、伸缩性、可用性等等的预期。当然,需要在这些(或其它)质量之间进行权衡,比如,功能性和上市时间,它们将能显著地改变问题领域。

Matt: 当然,所有有用的素材都在这些文章中了。虽说这样,完成一个高质量(性能)系统是相对的——我从未看到关于如何维护品质一个好的建议——这是治理部分的内容。看上去 IT 系统似乎注定一开始很鲜亮、然后衰退、最终消亡,接着再全部重新构建一遍。连确保它们至少偶尔有一个漂亮的外观都很难。

问题 6:实现可伸缩性和性能调优通常被看作是一种“救火”措施;目标是是立刻修正问题。你们在一个成熟的代码库上是如何跟踪性能衰退的?

Randy: 在 eBay,所有项目都经过了严格的负载和性能测试阶段。在将项目发布到网站之前,我们使用这一阶段来检测并解决潜在的性能问题。

Matt: 我们经过的是一个不同的过程——我认为这些都是在应用程序运行的时候才能检测到的。要确保一个应用被有效地划分并部署到真实环境的服务器上。如果一切正常,再把它部署到另一个服务器上,然后再是另一个,等等。确保在早期初次公开展示过程中,你投入了有效的监测和管理基础架构以捕获性能问题。

不要试图在部署之前就捕获性能问题。你不可能重建真实环境中的条件,因此你不可能得到真实可靠的测量结果。

Blaine: 是的,监测。非常仔细的监测。我提到的是监测吗?监视迟缓现象。当你看到一个衰退时,回去检查一下你的改变记录。应该很容易定位,因为你通常所做的是增量部署,不是吗?

FiveRuns: 我们得补充一下,适当地建立一个基线是很重要的:一个已知的好的性能表现。并且试图梳理出任何交织于最终用户功能瑕疵的性能问题——有时这些瑕疵看起来只和功能有关,但实际上也包含了性能问题。

问题 7:那么捕获问题的真正重要的衡量标准是什么?

Randy: 衡量标准就是那些影响你业务(例如,页面负担、用户响应时间)的衡量标准,以及使你受限(例如,内存、CPU、网络带宽等)的衡量标准。正如你可能想象的,eBay 基础架构的一些部分是受 CPU 限制的,另一些是受内存限制的,还有一些则是受 IO 限制的。当然,墨菲法则(一种幽默的规则,它认为任何可能出错的事终将出错)确保了你没有严密跟踪的衡量标准就是那个对你不利的标准!

Blaine: 取决于你的应用。任何事都有响应时间。找到你认为花了最长时间的地方,对它们进行计时,如果结果随你所测量的比特位数的多少而非常不同,找到它们。页面装载时间在高于 250ms 时都是很重要的问题。在这个响应时间之内,用户(通常)都看不出差别,而任何优化(例如,针对 API)都是性能和成本的优化。

了解集群的当前状态;如果是超出了集群的处理能力,那就去增加处理能力,句号。没什么好说的,去买更多的机器就是了。不要再阅读本文了,去买更多的机器吧。如果处理能力是一个影响因素,而且你的应用并没有大的问题(无明显性能问题,你已经调优了 mysql 等等),去买机器吧。你可以让它运行得更快并节约了后面的花费,但同时,购买机器意味着你将减轻很多压力并给自己一个喘息机会以对应用正确实现可伸缩性。

Matt: 确保它与你的业务相关,确保你所采取的测量是有意义的。除非你知道当时正在执行什么业务功能,否则一个 CPU 测量是无意义的。

FiveRuns: 我们全体都同意最终的衡量标准是捕获了客户期望响应的那一个。通过响应,我们真正把整个系统中的其它元素汇集到了一起。例如,gmail 比其它邮件服务递送邮件更加迅速;因为它的“响应”(例如,从邮件被发送到在 gmail 中看到邮件之间所花的时间)满足了用户的预期,其它技术上的标准是无关紧要的。

问题 8:性能对应用程序的总体“健康”能起什么作用?

Matt: 性能是一个重要的部分,但仅仅是部分。虽然旧了一点,但 ISO 9126 依然是建立有关测量系统的衡量标准的很好入手点。

“健康”是个很有意思的概念。在医学里,身体里每个细胞的性能不能够被测量,但是大量细胞汇集在一起就有了“生命信号”,如脉搏、温度、血压和呼吸都是可以测量的。大系统应该以类似的方法进行测量——单个服务器的内存使用与整个系统在线用户数相比起来没什么用处。每个大系统需要一些关键的生命信号。

Randy: 性能绝对是基础。差的性能直接反映了底层基础架构的花销,以及用户的体验。这两者都是底线。一个性能低于预期的应用不是“完成”了的应用,一个缺乏必须功能的应用同样是没有完成的。

FiveRuns: 通常,我们都同意把性能不佳看做是一个大 bug,而当作一个大 bug,我们还得关注存在大 bug 的地方,这可能是另外一个大 bug。因此,我们认为健康是依赖于用户 / 所有者体验的一种东西。

可是,也有反例。例如,针对很小一部分受众的一个意在提供一些新颖功能的 Web 应用,其可伸缩性问题不被计入到应用的“健康”范畴。如果是一个工业级应用,比如 gmail,它一向有性能(或伸缩性或可用性)问题,那么其可伸缩性就给应用“健康”的带来了消极影响。

Blaine: 有时一个应用就是慢,因为它要处理很复杂的事情,加快速度是不可能的。这变成了一个交互和负载容量问题。有时应用慢是因为代码太烂,当负载增加时所有事情都慢下来了(尤其与触发锁的代码有关,例如,sql 锁或 nfs 所或任何种类的分布式锁)。

问题 9:真正的性能和感知的性能之间的存在概念差异。对修复来说哪个更重要?

FiveRuns: 感知的性能是最终用户感觉得到的,因此最应该修正。可是我认为感知的性能是很难测量的——即,它是依赖于上下文的,作为观察者,我们不能总是访问同一个上下文环境,而且我们不可能控制组成上下文的所有东西。

Blaine: 掩饰。感知的性能更重要。使用后台队列卸载工作,显示用户所期望的东西并且断定是怎么泄露到应用的其它方面的。使用 Javascript 轮询廉价的请求而不是集中到一个单一的昂贵请求。在请求开始的时候将开销大的事情拆成并行的,在请求结束的时候再把结果收集起来。

Matt: 我不同意——真实更重要。与其假装成某种情况,不如真的变成那种情况。

Randy: 这两者都重要:-)。感知的性能影响了用户体验,而所谓的真实性能会影响成本。这最终就是一个业务决策:此刻最大的痛苦是什么,因此要看哪个相对更优先。

问题 10:几乎每个星期,总有些人发布一个新的 Web 或应用服务器或数据库 /ORM 层软件。怎么看待这种情况?这是好事情——还是让 Job 调优更加困难了?

Blaine: 我使用 apache。它有其缺点,但是工作良好。我使用 MySQL,它也有其缺点,但是工作良好。没有应用可以解决你所有的问题;它们有些是让事情更容易理解或修正,有些的确更好,但是有些使得调试和修正更加困难。

至于数据库,拥有 DHT 并不能使你获得索引(index)。你需要一个分布式索引,只是你还不知道。BigTable 和相关开源项目都不是分布式的索引。MapReduce 不是分布式的索引。查明你的分布式索引是怎样的,自己构建它吧。

Matt: 这很好,但是可以更好。大多数同类产品都是大同小异的。能看到持续创新挺好,但是如果能看到每一类工具的数量少一些而完全不同类型工具的数量和差异多一些,那就更好了。

FiveRuns: 作为这种产品的制造者,我们对这个问题特别感兴趣!我们认为它是好事——它鼓励创新并给我们带来新的思路。但是我们专注于使用最好的工具组合——新的不见得就是好的。
s
Randy: 有选择是好事情。这取决于你怎么去选择。追赶潮流此刻不再比顽固坚持不能工作的东西更有生产效率。我要说的是在一个像 eBay 这样 24x7 都要运转的站点,我们在使用经证明是好的技术时需要非常小心。这是我们对公司的责任。在我们考虑引入任何新东西的时候,在我们考虑将其应用到站点之前都要经过非常广泛的评估。

问题 11:那么在这一领域还有哪些内容经常被曲解?

Matt: 嗯,我觉得让人有点失望的是,当一个好思想被商业化或者更通用化时,这个思想的质量就变差了。比如数据存储——很难建立一个既快速又可存储大量数据的软件。很明显,为了商业化(即,有大量潜在客户)两者都可实现当然最好了,但是这就意味着最终是一个妥协的产物,既不快也不大——不管厂商怎么宣传!

不是说这就是普遍现象或者总会是这样。

Blaine: 你只能通过使用软件实现伸缩性。“语言是不能伸缩的。框架是不能伸缩的。而架构是可以伸缩的。”

伸缩性是一个社会问题。协调你的业务、操作和工程师们是极其关键的,如果你在这方面不成功,你实现伸缩性的努力也会失败。如果你的公司不理解需要多方协调以培育成功,那么你也会失败。YouTube 正是通过正确的处理这一社会问题实现了伸缩性。他们购买服务器、有一个好的投资计划、有足够的带宽。他们选择一件事情,把它做好,以组织的方式决策伸缩性,在天才工程师们的努力下,伸缩性如魔术般被实现了。

你可能会失败。快速吸取教训,然后成功。没问题。不要构建开箱即可伸缩的服务,因为你或许会发现你的交互设计是错误的,你必须回过头重新来一遍。在这期间,那些没有构建伸缩性的人可能正确设计了交互,因而足足领先了你 6 个月的时间。

FiveRuns: 性能改进 / 伸缩性提升是一件“容易”的事情——修正性能或伸缩性问题不总是像外界看得那么简单——很容易因此受到指责且很难真正解决“所有”给定的约束。以我们的经验,修正性能和伸缩性问题需要对技术和问题领域两方面都有深入了解和经验。

Randy: 经常被曲解的是性能和可伸缩性这两者间的区别 ;-)
粗体

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×