在云应用程序设计中管理故障点

确保云应用程序可靠性的四项技术

随着基于 Web 应用程序的普及,这些应用程序的可靠性成为日渐重要的一个要求。在本文中,作者研究了应用程序可靠性在基于云的世界中的真实意义,并探索了一系列方法(减少、管理、检测和避免)来提高云应用程序的正常运行时间。

Peter Bell, 工程部高级副总裁, PowWow

/developerworks/i/p-pbell.jpgPeter Bell 是 General Assembly 的工程部高级副总裁和资深研究员,General Assembly 是一所以技术、设计和创业为主的大学。他经常出席国际会议,撰写了大量有关 JavaScript、领域特定语言、敏捷架构、NoSQL 以及需求和预估的文章。他出席了各种会议,包括 DLD Conference、ooPSLA、RubyNation、Code Generation、British Computer Society Software Practices Advancement 会议,以及 Rich Web Experience。Peter 在 IEEE SoftwareDr. Dobbs、IBM developerWorks、Information WeekGroovyMag 上发表过文章。



2012 年 3 月 26 日

可靠性意味着什么?

关于软件应用程序的可靠性,有许多不同的定义。我认为,最重要且实用的定义是……
系统的用户应该能够使用该系统实现他们的目标。

严格地讲,如果应用程序终止,只要没有人正在尝试使用它,那就无所谓。而且,假设从用户的角度来看应用程序运行正常,那么即使他们不知道的某个子系统当时正处于脱机状态,也无所谓。

同样地,如果因为应用程序的代码出错,用户不能执行预期的操作,那么正常运行时间也没有价值。

这些是主要的区别,可以让我们把注意力集中在那些真正有意义的事情上,即:用户能否从系统中得到价值,而不是任何指定的子系统当时表面上能否操作。

下面我们进一步了解有助于设计稳固、可靠的基于 Web 应用程序的四类技术:

  • 减少单一故障点。
  • 管理故障转移的方式。
  • 不仅仅检测应用程序的心跳。
  • 通过设计、开发、测试、部署策略主动避免故障。

减少单一故障点

提高可靠性的第一个方法就是减少或消除单一故障点的数量。基于云的架构将这个过程变得更简单,因为基于云的架构提供了更加抽象的计算单元。在云计算中,不需要考虑诸如为每台服务器配备两个网络接口卡并确保连接和电缆质量足够高以避免意外断网之类的事情。您也不需要考虑独立磁盘冗余阵列 (RAID) 等级,以及哪个品牌硬盘是否拥有可接受的平均故障间隔时间之类的问题。

潜在的单一故障点在很大程度上取决于应用程序,但值得考虑的公共领域有:

  • 域名系统 (DNS) 服务器,
  • Web 服务器
  • 数据库服务器
  • 文件服务器
  • 负载均衡器
  • 其他专用服务器
  • 第三方依赖性

图 1 概括了这些公共的故障点。

图1. 公共故障点
公共故障点

DNS 服务器

许多采用云计算服务托管应用程序的组织仍然使用独立的 DNS 服务器。重要的是确保自己或 DNS 服务供应商在不同数据中心拥有多台 DNS 服务器,并且都包含您应用程序的 DNS 记录。如果用户无法通过 DNS 解析访问应用程序,那么您的 Web 托管解决方案再强大也没有意义。请审查如何配置 DNS 服务器以确保 DNS 服务器方面不存在容易修复而且修复起来很便宜的单一故障点。

Web 服务器

在使用多台 Web 服务器,并想在多台 Web 服务器之间启用故障转移功能的时候,需要考虑两个关键的最佳架构实践。第一个是:不要使用 Web 服务器的本地文件系统持久化任何重要信息。对于习惯于为单台 Web 服务器编写应用程序的人来说,这是最常见的不同。您必须假定任何指定的服务器在任何时间都有可能发生故障,所以如果用户想上载文件或者想要记录信息,一定要在所有 Web 服务器都可以访问的单独文件系统或数据库中保存。这样,用户可以将图片上载到一台服务器,但在原始服务器停机的时候,仍然能够从其他服务器上访问上载的图片。

第二,您必须考虑如何持久化基于会话的信息。对于少量数据,可以使用基于 cookie 的存储,但要注意只在 cookie 中存储 ID 信息,因为 cookie 不安全,容易被用户篡改,而且最大容量只有 4KB。通常情况,您要么使用每台 Web 服务器上的本地会话存储和支持粘性会话的负载均衡器,这样会话内的用户都会一致返回同一台 Web 服务器,要么将所有会话状态存储在独立的会话服务器,该服务器将使用内存缓存或键值数据存储来持久化会话信息。在每台 Web 务器上存储会话状态并使用粘性会话,性能通常会更高,因为这样做减少了完成请求所需要的网络来回次数;但是,如果某台 Web 服务器停机,那么那台服务器上的所有用户会话都会丢失。在可靠性至关重要的时候,有必要使用独立的服务器负责会话存储。

数据库服务器

了解数据库服务器的需求,并选择合适的技术和伸缩策略,非常重要。例如,如果您有一个内容管理系统,读取操作频繁,而写入操作相对不那么频繁,那么您也许能够容忍数据库写入的单一故障点。在这种情况下,可以选择使用主从复制方式实现关系型数据库,在这个实现中,只有一个主节点,但在主节点中断时,从节点仍然可能继续提供读取服务。如果读、写可靠性都很重要的话,则可以考虑目前广泛采用的 NoSQL 数据存储,这样可以更加方便地将持久性分布到多个节点上,以提高可靠性和可伸缩性。

对于数据库来说,另一个重点是要考虑一致性方面的需求。许多 “Web 规模” 应用程序目前以节点间的即时一致性换取最终一致性系统上更高的可靠性和性能。对于最终一致性系统来说,并不保证不同数据库节点会在同一时间响应相同的数据。显然,对于银行应用程序来说,同一时间在不同的节点上查看不同的帐户余额是不可接受的,但令人惊讶的是,有多少系统可以接受数据的最终一致性,以获取更好的可靠性和性能作为回报。

文件服务器

前面说过,在构建可靠的系统时,可能不希望将重要信息存储在单个 Web 服务器上。相反,所有 Web 服务器将使用单独的共享文件服务器来存储和获取静态文件。不论使用什么文件服务器,是否使用自身提供冗余和故障转移功能的基于云文件系统,还是自行管理,使用负载均衡和多台文件服务器连接到一个或多个同步的文件系统,都要确保不要因为文件服务器而导致单一故障点。

负载均衡器

重要的是,要认识到负载均衡器本身也会带来单一故障点问题。请花点时间了解负载均衡在您的云架构中的实现方式,确保如果有一个负载均衡节点停机,不会造成整个应用程序停机。

其他专用服务器

一个最佳架构实践就是将应用程序子系统之间的耦合降到最小,使之可以在不影响其他子系统的情况下伸缩和/或重架构任何给定的子系统。随着应用程序的成长,经常需要为每个子系统增加一台或多台服务器。常见的专用服务器包括:对外发送邮件广告的电子邮件服务器,执行视频编码或图像处理等操作的处理服务器,在不增加生产数据库服务器负担的情况下提供更丰富报告功能的报表服务器。

在架构这类系统时,最重要的是确定这些系统的正常运行时间对于该系统可感受到的正常运行时间的重要程序。如果有一个企业级消息应用程序使用电子邮件交付相当一部分消息,那么很明显邮件服务器对于正常运行时间的感受一定非常重要,因此有必要提供多台电子邮件服务器之间的故障转移。如果您的邮件服务器只是偶尔地发送一些 “忘记密码” 或 “状态” 邮件,那么您可以接受只配置一台邮件服务器潜在的宕机时间。

第三方依赖性

应用程序的成功运行通常依赖于第三方服务。如果通过 Facebook 提供登录功能,那么 Facebook 的 OAuth 服务器就成为您系统的一个故障点。如果提供 LexisNexis 数据的搜索,则它的门户就变成您应用程序的一个故障点。这是您需要关注的一个领域,在确定如何才能最好地管理这些潜在的故障相关风险时,您要研究这些第三方服务对您的用户体验的重要性,需要做到什么样的实时交互,以及服务停机的可能性。

例如,依赖第三方网站提供身份认证是一大风险。但是,如果第三方是 Facebook,那么这个风险是可以接受的;相比小规模能力有限的供应商,这么大的组织停机的可能性要少得多。如果这种风险太大,则要确保用户也可以使用其他凭据登录,例如电子邮件地址和密码,这样即使 Facebook 的 OAuth 服务器不可用,用户依然能够访问应用程序(如图 2 所示)。

图 2. 更多公共故障点
更多公共故障点

在另一个极端上,集成第三方系统来发送电子邮件的风险不大,因为少量停机是几乎察觉不到。电子邮件天生就是异步的,但较长的停机时间(相当于并包括服务商意外停止服务)的可能性依然存在。如果想缓解风险,请确保自己有一个可以将第三方系统更换为其他供应商的计划,或甚至在可接受的时间内替换为内部的解决方案。


管理故障

很重要的一点是,要认真思考故障转移的工作方式,并对其进行测试,以确保结果符合预期要求。如果不使用粘性会话,那么在使用设计良好的负载均衡器时,Web 层的故障转移通常是无缝的。至于数据库的故障转移,您必须了解自己要实现什么样的持久存储,但多数数据库都有良好的文档,确切地描述了节点发生故障时所发生的情况。管理互操作子系统之间的故障转移则需要精心计划。例如,如果某台 Web 服务器向一台邮件服务器发送请求,邮件服务器接受了请求,但在发送消息前,发生了故障,这时会怎样?

对这类问题最简单的解决方案可能是使用一个数据库作为不同子系统的共享后台。每个子系统在处理作业的前后都更新作业的状态。时间戳使查找阻塞在处理过程中的 “丢失” 作业并定期整理交给另一台机器处理的工作变得简单。

目前默认方案的另一种做法是,使用某种消息队列来处理子系统之间的消息传递,并为消息交付提供一定的保证(如图 3 所示)。

图 3. 没有本地存储的故障转移
没有本地存储的故障转移

有多种消息队列可供使用。要确保准确地了解所选择的消除队列实现方式,以防消息被收到却没有处理;还要确保运行消息队列的计算机发生故障时,消息队列本身的行为容易理解。


检测故障

如果您关心可靠性,那么监视和跟踪系统所有元素的正常运行时间非常重要。您可能需要在所有服务器上设置某种基本的 “心跳” 监视,以确保服务器正常响应,但您还要确保拥有更丰富的监视机制,以验证邮件服务器确实成功发送了邮件,并且在请求文件的时候文件服务器确实能够成功地提供已知的文件。

全面考虑发送给 Web 服务器的监视请求以确保这些请求能够全面地测试系统,尤其重要。如果主页是静态页面,而网站其余部分是动态的,需要从数据库获取内容,则不要测试主页的加载情况。如果某个应用程序需要通过企业身份管理系统对用户进行身份验证,然后再从企业资源计划 (ERP) 系统获取数据,那么要确保监视脚本能作为测试用户(已经添加到 ERP 系统)身份登录,并确保来自 ERP 系统的数据正确显示在 Web 服务器发回的请求响应中。有必要在子系统监视之外拥有这种端到端监视,以确保应用程序正常工作。

有些公司(例如 Etsy)目前对这些 “端到端” 测试的应用更进了一步。Etsy 拥有著名的内部业务测量指标,用来测试其站点的工作情况。如果应用程序的表现超出了业务测量指标的预期范围(例如给定时间段内的总销量),那么会通知工程团队,以便让他们去分析寻发生的情况并修补任何潜在的问题。应该坚持思考应用程序的真正意义是什么,如何跟踪它,以及应用程序在预期范围内中断时如何自动通知团队。

而且,还应该考虑对某些事情进行自动跟踪,例如 bug 报告的数量,这样如果在短期内出现问题高峰,系统可以自动通知团队,告诉他们应用程序可能有问题。


避免故障

有些故障是不可避免的,但很多时候,借助于设计良好、容错的系统,相当一部分停机是由于应用程序代码中的错误造成的。这时,不管应用程序运行正常或响应正常均没有意义:如果用户不能完成使用您的应用程序想完成的任务,对他们来说,这个网站实际上就是停机了。因此,另一个重点就是,拥有一个良好的设计、编写、测试、部署代码的策略,将应用程序正常运行时间提高到最大。

测试驱动的开发

确保应用程序设计良好并提供的功能符合要求的最有效途径就是,让开发团队采用测试驱动的开发 (TDD) 方法。这个过程既能确保代码的正确性,还能实际地提高设计的适应性和质量。

持续集成

软件开发最重要的一个格言是,“如果它伤害了您,那么就常常这样做 (if it hurts, do it more often)。"如果每月运行集成测试确实有此困难,就努力每周运行,并自动化此过程,直到开发人员每次将代码签入版本控制系统时轻轻一点即可执行集成测试为止。

持续部署

2010 年最重要的一本技术图书是由Jez Humble 和 Dave Farley 合著的持续部署。该书介绍了如何创建强大而设计良好的部署管道;如果有兴趣提高应用程序的可靠性,一定要阅读此书。书中的概念包括:蓝-绿部署(有两个几乎相同的生产环境,可以用来进行零停机的发布和回滚)、金黄部署(充许您在将代码发布到整个用户基之前将新代码发给用户子集进行测试)。使用功能切换,甚至可以向程序选择出来的用户交付功能,从而方便地用不同用户群对功能进行测试。


结束语

利用基于云的基础设施创建高可用的应用程序,比以往任何时候都更加容易,但重点在于全面考虑所有故障点,确保有处理故障的策略,确保在故障转移期间不会丢失重要数据。另外,也有必要考虑采用 TDD、持续集成、持续交付等方法,确保应用程序的工作表现一致符合预期。如果因为生产代码中的 bug,用户不能完成自己需要完成的任务,即使服务器正常运行,也没有意义。

参考资料

学习

获得产品和技术

  • 查看 IBM SmartCloud Enterprise 可用的 产品映像

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Cloud computing
ArticleID=806893
ArticleTitle=在云应用程序设计中管理故障点
publish-date=03262012