在复杂系统中,故障是不可避免的。在应用的整个生命周期中,极有可能的是,任何可能发生的灾难未来终会发生。因此,开发者需要充分了解那些可能会对应用产生影响的不同类型的故障。只有了解这些故障风险的性质以及发生的可能性,才能制订合适的对策来缓解和消除这些风险的影响,同时这也是快速响应突发事故的基础。
作为一名有责任感的服务设计师,开发者需要找到微服务应用中所有可能的故障类型,然后将这些故障类型按照预期的频率和影响进行排序,最后决定如何减轻这些故障造成的影响。本文将介绍一些微服务应用中常见的故障场景及其出现的原因。
一个案例服务与其他组件的每个交互点都预示着一个可能出现故障的地方。故障主要发生在四大领域中:
第一,硬件——服务运行所依赖的底层物理基础设施和虚拟化的基础设施;
第二,通信——不同服务之间的协作以及服务与外部第三方之间的协作;
第三,依赖——服务自身所依赖的服务的故障;
第四,代码——服务本身的代码错误,比如工程师引入的代码缺陷。
1.硬件故障
不论服务是运行在公有云、内部系统上还是使用PaaS服务,不管它们是服务器机柜、虚拟机、操作系统还是物理网络,服务的可用性最终都是依赖于支撑这些服务的物理基础设施或者虚拟设施的。
应用中物理层的不同故障其范围各有不同,但是这些故障通常都是灾难性的,因为硬件出现故障会影响组织机构中许多服务的正常运行。
通常来说,开发者可以在系统中适当地做一些冗余设计,以降低硬件故障的影响。如果应用部署在AWS这样的公有云上,那么开发者一般可以将服务的副本部署在多个可用区(zone)中(可用区是AWS的概念,指的是一个范围更大的区域(region)下位于不同地理位置的数据中心)。
需要重点注意的是,硬件冗余会增加额外的维护成本。这些冗余方案有的过于复杂而难以设计和执行,还有的方案则纯粹是金钱的浪费。为应用选择合适的冗余级别是需要认真考虑的,我们要综合考虑故障发生的频次和影响以及消除这些极为罕见的故障事件的成本代价。
2.通信故障
服务之间的通信也会出现故障,DNS、消息传递和防火墙都是可能的故障源。
通信故障既会影响内部网络调用,也会影响外部的网络调用,比如,market-data服务与外部API服务之间的网络通信质量下降会导致出现故障。
网络和DNS故障都是比较常见的,不管是系统中防火墙规则的修改还是IP地址分配,抑或是DNS主机名传播,都有可能导致网络和DNS故障。网络问题是很难消除的,但通常都是由人的介入(有新服务服务发布或者修改配置信息)导致的,所以避免这些问题最好的办法就是确保对配置修改进行全面而可靠的测试,并且确保在问题出现以后,可以很容易地回滚这些配置信息。
3.依赖故障
故障可能出现在微服务所依赖的其他外部服务,也可能出现在微服务内部的依赖(如数据库)中。比如,market-data服务用来保存和获取数据的数据库会因为底层硬件故障而出现问题,或者因为达到容量上限而出现故障。
这种依赖故障对整个系统的可用性的影响是极大的。
除了诸如超时和服务停机这类运行层面的故障源,设计或者开发不当也容易导致出现依赖性错误。比如,某个服务A依赖于另一个服务B的端点url,而修改这个服务B时没有保持向后兼容,更甚者,在没有执行适当的下线流程的情况下完全将该服务B移除。这都会导致服务A出现故障。
4.服务实践(开发和部署)
最后在服务开发和部署阶段,如果工程实践不到位或者有欠缺,也都会导致生产环境出现故障。这种问题也很普遍。比如,有的服务设计方案很差、测试也不充分、部署也有问题。有的团队在测试阶段不能及时发现问题,而对生产环境中的服务的各项功能又没有进行全面的监控。还有的服务无法有效扩展:所提供服务器的内存、硬盘或者CPU利用率达到了上限,因此性能下降,乃至服务完全没有响应。
每个服务都对整个系统的有效性有贡献,所以如果一个服务的质量水平特别低,就会对许多功能的可用性产生不利的影响。
希望本文介绍常见故障清单能够帮助大家避免同类问题。同时故障清单也需要迭代更新,落地实践也很重要。
摘取自 摩根·布鲁斯和保罗·A.佩雷拉的《微服务实战》
网友评论