技术开发 频道

来自Amazon的经验:七招提高大型网络服务性能

【IT168 专稿】    在网络化发展初期,工具和框架十分匮乏,但是仔细回想一下,却会发现这些早期网络服务确实是可扩展的。现在,工具越来越丰富,我们也越来越希望有更好的交互、性能和可扩展性。尽管如此,我们还是建议只根据需求进行构建,尽量利用其他人的工作成果,也就是要谨慎选择优化的时间、目标和方式。

    不要过早优化

    笔者参加的第一个扩展相关会议是亚马逊的“假日扩展”会议。当时是1998年6月3日,会议主持是Bob Vadnais,因为没有会议室,地点就定在他的公寓。会议上,大家讨论了两种战略:一种是用规模更大的服务器,另一种就是进行优化调整。总之,就是通过扩展满足当时的需求。

    当时,亚马逊网站即将迎来第三年的运营,网站流量相当大。其重点是提高客户体验和以最快的速度发展。就如它的口号“尽快做大”一样。虽然大家把重点放在发展上,但是大家都明白,当战略重点转向成熟的架构和持续的扩展上时,还会遇到更多的挑战。

    一直以来,风险型技术投资的成功率是10%。因此,如果有人让你构建一个可扩展的网络服务,你应该问:“你确定吗?”与其把时间和资源用在扩展上,还不如用在改善客户体验和提高流量上。这样或许不但可以在产生最小副作用甚至无副作用的情况下解决问题,还能随着网站的发展和流量的提高进行扩展的自由。

    到亚马逊构建网络服务架构时——比如S3(简单存储服务)和EC2(弹性计算云)——亚马逊已经对网络服务的扩展有了很深的了解,也对需求做了比较系统的定义。

    利用他人成果

    在过去10年里,构建大型、动态网络服务的难度减小很多。其中主要原因有三个:SOA、云计算,以及ASP.NET、Django、Rails和Sping等网络应用框架的出现。

    这些发展不但促进了模块化和关注点分离的发展,也带来了责任的分离。因此,要尽量利用别人的工作成果或服务,只构建自己有能力构建的部分。因为与其把时间和资源用来构建或定制一个网络应用框架,还不如用来改善业务逻辑。虽然框架必不可少,但是它几乎不能带来任何客户价值的增长,所以在这方面花的时间只能起到事倍功半的效果。

    不要过度优化

    在亚马逊早期,那些促使流量模式偏离高斯预测的事件都登上了报纸头条。在美国,流量峰值因为受到时区分散的影响而没有受到很大冲击。但当亚马逊发展到单时区市场(比如德国)后,开始出现新的高峰,而这些高峰又倾向于出现在重要球赛的开始或结束时间。

    在最近一次关于决策类型和各种随机因素对结果影响的测试中,Nicholas Nassim Taleb再次看到他称之为“黑天鹅”的现象:最不可能出现和最不可预测的事件往往产生最大的影响。他认为,在无法预测的领域,比如金融和商品市场,对效率的追求会增加其脆弱性。比如,管理宽松会造成短期需求增长进而使商品价格翻倍。他建议:“避免优化,其实有一点冗余也是不错的。”

    大型网络服务的操作员往往喜欢最大程度地优化服务器的性能。在当前的经济情况下,这种做法可能还会得到推荐。

    但是,网络流量模式可能会比较“过激”。以前曾称这种现象为“点杠效应”,即由于许多网络用户的同时操作而造成流量过载。而现在,由于发生同时访问网络的机会更多、社会圈子越来越集中、社会网络和智能手机应用的爆炸性发展,这种现象会更常见而且规模更大。这还没算上恶意流量冲击。此外,各种突发事件还会影响到性能的提供,比如软件版本的低效,或如2003年8月发生的美国东北部大规模断电。冗余经常只被视为一种提高可用性的措施,即通过冗余绕过有故障的部件。但是在极端情况下,它还可以做为保持供需平衡的措施。

    利用云计算

    Animoto是一种可以利用人工智能制作专业级音乐视频的应用程序。该程序运行于Amazon EC2上。在一段时间里,它只用了平均40台服务器。但是突然之间,Animoto变得很受欢迎,服务器的使用量也暴增到3500台。显然能进行这种规模扩展的应用是非常有弹性的,而且在不需要的时候可以不用花费多余的成本,确实很方便。

    不要仅按目标优化

    只根据预测的流量设计扩展性能很容易遇到危险情况。因为一则很难建立准确的模型,二则简化措施和乐观假设也会抵消一些变数。用Taleb的话来说,你不能“用模型的不确定性来设计确定的东西”。还有更大的危险:如果你的网络服务走向成功,那么你就会发现需求要比当初预计的多——虽然可能不会发生在明天的某个黄金时间段,却很可能在后天你最意想不到的时候发生。

    充分利用测试

    扩展性测试的理想情况应该是:运行在与生产环境完全一样的环境下,并且一直运行到发生故障。常用的故障测试是“波音777机翼负载测试”。除了分析首先发生故障的因素外,我们还要找出能让应用或服务在不使用故障部分的情况下运行的办法;然后再次测试,找到下一个故障点,有时候可能还要与 Monty Python的“黑骑士”场景做对比。

    运行大型网络服务的一个难点就在于怎么实现一个高真实度的测试环境。虽然没有什么非常简单的办法,但是我们发现使用计算云中的虚拟资源可以让问题变得比较容易处理。在这种方式下,我们可以获得更高的真实度(运行相同的系统映像)和分离度,获得更高的测试灵活性,得到可供分析的结果或问题,并以更高效的方式使用资源。

    几个重要的关注点

    要构建一个可扩展的网络服务,最大的挑战就是在面临故障和极端访问模式时怎么处理耐久性、可靠性、性能和成本之间的平衡。

    对于持久层来说,这个问题更为严重。亚马逊的Werner Vogels指出“最终一致性”可以解决这个大规模扩展的可靠系统问题。eBay的Dan Pritchett也 从另一个角度讨论了这个耐久性问题。

    Sun的Craig Russell也讨论过ORM(对象关系映射层)问题。ORM得到了广泛采用,但同时也带来扩展上的问题。有了ORM,储存在持续层的数据是作为自然对象语言中的对象提供给应用程序,因此简化了持续层的实施,有利于关注点的分离。但ORM带来一个不可避免的副作用,就是缺乏扩展的透明度,无法得到查询的最终结构,无法了解读取多少数据,以及无法得知相关成本。

    在构建表示层的时候应该以自动化、面向恢复而且无限制的方式设计扩展性。谷歌的Steve Souders在他的文章中对前端性能进行了详细讨论。他列举了一系列非常好的实践,这些实践除了可以减少延迟外,还能提高前端的扩展性。

    还有网络。因为它有“增加价值”的功能,因此随着功能的增加,复杂性也会相应提高。现在的网络有许多与私有信息相关的功能。我们的目标就是使网络尽量简单、稳定、便宜。

    最后,浏览网络的方式以及浏览的内容也会影响到网络服务的性能和可扩展性。Akamai Technologies公司的Tom Leighton在文章《提高网络性能》中从比表示层更深的角度评估了转换能力、延迟和可靠性对性能的影响,还介绍了利用内容呈现方式突破瓶颈的方法。

    虽然构建可扩展的网络服务要面临许多困难,但是我们应该学会利用最近几年迅速发展起来的各种技术。或许现在的网络服务比以往面临着更多难题,但是很多情况下,我们都无须从零做起,因为我们可以利用已有的成果。

0
相关文章