Azure可用性保障最佳实践中文版

作者:王文勤
时间:2017-12-10


1,应用程序设计

  • 避免任何单点故障
    所有的组件、服务、资源以及计算节点都应该部署成多个实例,以此来避免单点故障导致可用性受影响。比如虚拟机资源,同一应用的虚拟机要部署成多实例,当单个实例故障时,服务不受影响。
    认证机制也要避免单点。将应用程序设计为可以通过配置来使用多实例,并将不能自动化的平台改造成能自动检测失败,并将请求跳转到没有失败的实例上。

  • 按照服务等级协议来隔离服务。
    假如一个服务是由重要和比较不重要的工作负载构成,应该以不同的方式管理并指定服务的功能和实例数来满足它们的可用性需求。例如,使用集群隔离将重要客户与比较不重要客户分开,防止某一方的流量将服务占满,影响另一方的使用体验。隔离的种类还有机房隔离、读写隔离、动静态资源隔离、热点隔离、爬虫隔离等,都对服务稳定性有重要意义。

  • 最小化外部依赖,对必须要的依赖深刻理解并从容应对。
    尽可能的减少不同服务的数量,并确保理解所有的功能以及系统中服务的依赖关系。这包括这些依赖的本质,以及每一个在故障或性能降低时对整体应用的影响。微软为大部分服务提供99.9%的可用性,这意味着应用程序依赖的每一项附加服务有可能使系统的可用性降低0.1%。比如有三个外部服务,每个服务单独的可用性都是99.99%,当系统依赖这三个服务时,系统的可用性变成了99.96%,

  • 尽可能将任务和消息设计为幂等(安全重复),使得重复的请求不会引起问题。
    例如,一个服务可以作为消费者,处理来自系统其他部分发送的消息。如果消费者在处理消息后,还没确认消息已被处理时失败了,生产者可能会提交一个重复的请求,这个请求可能会被作为消费者的另一个实例来处理。因此,消费者和他们执行的操作应该具有幂等性,来保证重复前一个操作不会使结果无效。这就是说要检测重复的消息,或者通过乐观的方法去处理冲突进而保持一致性。

  • 使用消息代理为重要的事务保证高可用性。
    许多初始化任务或者连接远程服务都使用消息在应用程序和目的服务之间传递指令。为了获得性能,应用程序应该可以具备在发完消息后,无需等待回复,直接返回处理更多的请求的能力。为了确保消息的发送,消息系统应该提供高可用性。Azure消息总线消息队列执行至少一次语义。这意味着尽管在某种情况下可能会发送重复的副本,但是每一条放到队列的消息都不会丢失。如果消息处理是幂等的,重复发送则不是个问题。

  • 将应用程序设计为当达到资源限制时可适当降级,并采取适当的措施将对客户的影响降到最低。
    在某些情况下,应用程序的负载可能会超出,导致可用性降低,或连接失败。缩放可以缓解这种情况,但也会因资源可用性或成本等其他原因达到限制。将应用程序应设计为在这种情况下可自动降级的。例如,在电子商务系统中,如果订单处理子系统处于高压状态或者完全故障,可以先暂时禁用其系统,让其他浏览产品目录等功能继续工作。适当地推迟像故障的子系统推送请求。例如仍然让客户提交订单,但同时要保存订单,以便在订单子系统稍后再次可用时进行处理。再比如,当CDN故障时,可以修改域名解析,绕过CDN,直接回源,快速止损,这也是一种降级策略。

  • 适当处理急剧突发的事件。
    大部分应用程序需要处理不同时间不同的负载量,例如业务应用程序中上午出现的第一波高峰,或者电子商务网站发布新品时。自动缩放有助于处理负载,但附加的实例上线并处理请求的过程是需要时间的。为了防止突发的意料之外的活动高峰,应该将应用程序设计为将请求加入其使用的服务队列,并在队列接近完全容量时适当降级。确保在非高峰时有足够的性能和容量来清空队

2,部署和维护

  • 为每一个服务部署多实例。
    微软为创建和部署的服务保证可用性,但这前提是为每个服务角色部署至少两个实例。这样,确保一个实例不可用时还有另一个可用。这当你要在线升级系统时尤为重要,实例可以中断和升级,而其他实例将继续保持联机。资源允许的情况下可以部署三个实例,保证稳定性。
  • 在多个数据中心托管应用程序。
    尽管很少发生,一整个数据中心还是可能因自然灾难或者网络故障而失联。至关重要的应用程序应该托管在多个数据中心,以提供最大的可用性。这样做还可以降低本地用户的延迟,并在应用程序升级时进一步提供弹性。
  • 自动化和测试部署与维护任务。
    分布式应用程序由多个部分组成,这些部分必须一起工作。因此,部署应该通过使用脚本或部署应用程序的测试和验证机制达到自动化。这些脚本和应用程序可以更新验证配置,自动化部署过程。自动化技术还用在所有或部分应用程序的更新中。务必全面验证所有的过程,确保错误不会引起其他的停机时间。所有的部署工具必须有适当的安全限制来保护部署的应用程序下,应用程序或服务的配置设置是可以在不重启实例的情况下进行更改。角色公开可以处理的事件以检测配置更改并将其应用到应用程序的各组件中。然而,一些核心的平台的配置更改还是需要重启角色的。在构建组件和服务时,将其设计为不需要重启整个应用程序就能接受配置更改,以实现最大化可用性并将停机时间降到最小。
  • 使用升级域来实现零停机升级。
    Azure计算单元(如web角色或worker角色)已配置到升级域。升级域将角色实例分组,因此,在发生滚动升级时,升级域里的每个角色都会依次停止,升级,重启。这样最大程度减少对应用程序可用性的影响。可以指定在服务升级时,应该创建几个升级域。关于升级域的定义可参考文档https://docs.microsoft.com/zh-cn/azure/service-fabric/service-fabric-cluster-resource-manager-cluster-description。
  • 为Azure虚拟机配置可用性集。
    在一个可用性集中放两个或更多虚拟机保证其不会部署在同一个容错域中。为了最大化可用性,应该为系统使用的每个重要虚拟机创建多个实例,并将这些实例放在同一个可用性集中。如果正在运行多个不同目的的虚拟机,那么为每一个虚拟机创建一个可用性集。将每个虚拟机的实例添加到每个可用性集中。例如,创建web服务器和报告服务器的虚拟机,为web服务器创建一个可用性集,为报告服务器创建另一个可用性集。在web服务器可用性集中添加web服务器虚拟机的实例,在报告服务器可用性集中添加报告服务器虚拟机的实例。

3,数据管理

  • 在Azure存储中异地复制数据。
    Azure存储中的数据自动在数据中心复制。为了更高的可用性,使用读取访问异地冗余存储,它将数据复制到次要区域,并提供次要区域数据的只读访问权限。这样即使一个区域完全中断或有灾难时,数据也会得到持久保护。
  • 异地复制数据库。
    Azure SQL数据库和Cosmos DB都支持异地复制,因此可以在其他区域配置辅助数据库副本。当数据中心中断或者无法连接到主数据库时,可以使用辅助数据库副本进行查询和故障转移。
  • 尽可能使用乐观并发访问和最终一致性。
    通过锁定(悲观并发)阻止访问资源的事务会导致性能差,可用性低。这些问题在分布式系统中会变得更加严重。在许多情况下,谨慎的设计和技术(例如分区)可以降低发生更新冲突的几率。在数据复制的地方,或者在单独更新的存储中数据读取的地方,数据只能保持最终的一致性。但其优势远远超越了通过事务来保证实时一致性对可用性造成的影响。
  • 使用定期备份和时间点还原,保证符合恢复点目标。
    定期自动备份没在其他地方保存的数据,并验证当故障发生时可以可靠地还原数据和应用程序本身。数据复制并不是备份功能,因为通过故障、错误或恶意操作导致的错误和不一致性会复制到所有的存储中。备份过程必须是安全的,以保护传输中和存储中的数据。数据库或者部分数据存储通常可以通过事务日志恢复到之前某个时间点。微软云为存储在Azure SQL Database中的数据提供备份工具。数据被导出到Azure blob存储中的备份包里,并且可以下载到本地安全的地方。
  • 启用高可用性选项来维护Azure Redis 缓存的辅助副本。
    当使用Azure Redis缓存时,选择标准选项来维护内容的辅助副本。

4,错误和故障

  • 超时概念介绍。
    服务和资源可能会不可用,从而导致请求失败。确保为每个服务或资源以及访问服务和资源的客户端设置合适的超时时间。(在某些情况下,特定客户端实例可以设置较长的超时时间,这取决于客户端正在执行的上下文以及其他操作。)太短的超时时间可能会对有延迟的服务和资源造成过多的重试。太长的超时时间可能会在大量请求等待服务响应时引起阻塞。
  • 重试由短暂故障引起的失败操作。
    为原本不支持自动连接重试的对服务和资源的访问设置重试策略。使用重试策略,随着失败次数增多,重试之间的间隔增大,以避免资源过载,允许资源恢复并处理排队的请求。重试时间间隔太短的话可能会加剧问题。
  • 当远程服务不可用时停止发送请求以避免级联故障。
    有一些暂时性的或其他故障,其严重程度从部分连接失败到服务完全故障,需要比预期较长的时间恢复正常。另外,如果一个服务非常繁忙,系统某一部分的故障可能会导致级联故障,导致许多正在占用系统资源(如内存、线程、数据库连接)的操作卡住。不要一直重试一个不太可能成功的操作,应用程序应该迅速接受操作失败的事实,并处理故障。可以使用断路器模式,在特定时间拒绝特定操作的请求。
  • 多实例模式,缓解特定服务脱机或不可用造成的影响。
    设计应用程序时尽可能利用多实例不影响操作和已存在的连接的优势。使用多实例,并在其之间分发请求,检测并避免向故障实例发送请求,从而使可用性达到最大化。
  • 尽可能降级到不同的服务或工作流。
    例如,如果写数据库失败了,可以暂时把数据存储在blob存储里。当服务又可用时,将写在blob存储里的重新写到数据库,此时要根据数据大小控制写的速度,避免大量数据同时写,导致拥挤、失败。在某些情况下,失败的操作可能有代替的方案,即使一个组件或服务故障了,也能使应用程序正常运行。如果可能的话,当主服务脱机时,检测失败的请求并将请求重定向到其他可以作为替代的服务上,或者到备份,功能减少但可保持核心操作的实例上。

5,监控和灾难恢复

  • 针对可能的故障和故障事件提供丰富的检测,将情况报告给操作人员。
    对于还没发生过的有可能发生的故障,提供详细的数据,使得操作人员能够定位原因,缓解问题,确保系统可用。对于已经发生的故障,应用程序应该能返回正确的报错信息,并尝试继续运行,虽然这样会降低功用。不论哪种情况,监控系统应该捕获到详细的信息,使得操作人员能快速止损,做恢复,如果需要的话,还能使设计者和开发者能够修改系统防止这种情况再发生。
  • 通过检查功能来监控系统健康状态。
    应用的健康状态和性能可能随着时间会降低,直到有故障了才被发现。实施检测或定期从应用外部去检查功能。这些检查可以很简单,就像度量整个应用程序,或者应用程序的单个部分,或者应用程序使用的单个服务,或者单个组件的响应时间一样。检查功能可以执行流程来保证生成有效的结果,度量延迟时间,检查可用性,并从系统中提取信息。功能检查监控产品的核心功能是否正常,比如微信的聊天功能、谷歌的搜索功能。、生。
  • 定期检测所有的故障切换和故障回退系统,以确保其可用并按预期工作。
    系统的更改和操作可能会影响故障切换和故障回退功能,但是在主系统故障或过载之前可能不会发现这种影响。在被用来解决线上问题之前,先测试系统。
  • 测试监控系统。
    自动故障切换和故障回退系统,以及通过仪表板手动查看系统健康状态和性能,都需要依赖于监控和检测功能正常运行。如果这些监控和检测异常,则会丢失重要信息,或者报告不正确的数据,操作人员可能无法意识到系统不正常或故障了。
  • 追踪长时间运行的工作流的进度,并在故障时重试。
    长时间运行的工作流经常由很多步骤组成。确保每一步都是独立的,并且可以重试,以此减小回滚整个工作流的几率,或需要执行多个补偿事务的可能性。通过计划代理监督模型来实现跟踪长时间运行的工作流的进度。
  • 灾难恢复计划。
    针对任何可能影响系统可用性的故障,创建一个可接受的,充分测试过的恢复计划。为重要的应用程序选择多站点灾难恢复架构。为灾难恢复计划确认一个所有者,包括自动化和测试。确保这个计划有详尽的文档,并且尽可能多的将步骤实现自动化。对于相关的事务性的数据要有备份策略,并且定期测试备份还原的结果。培训操作人员执行此计划,并且定期演练来验证和改善此计划。
发布了82 篇原创文章 · 获赞 0 · 访问量 2556

猜你喜欢

转载自blog.csdn.net/zhinengyunwei/article/details/104049768