面向失败的设计
面向失败的设计
软件架构也发生了一系列变化,从面向功能的单一系统架构,分布式架构,到面向业务的中台化架构,到现在的面向生态的云化架构。云化架构为我们带来了开放的生态,允许我们与更多的团队、更多的技术栈协同工作,但也带来了更多的不可控。因此在云时代,传统软件架构思想原则基础上,面向失败的架构设计也愈发越来越重要。
软件工程师通常会对这三个方面进行优化:可用性、性能、容错能力。
- 可用性:系统正常响应和避免停机的能力。
- 性能:在这里特指对延迟或资源成本的最小化。
- 容错能力:系统从非正常状态中恢复的能力。
对于失败的定义,在上面三个维度也是有所不同,而如果以面向对象、功能或者业务视角来看,又是另一类维度的划分。抽象来说,面向失败的设计,就是假设系统必然会发生失败,天然为了失败而存在的,贯穿于软件整个生命周期的设计思想。譬如我们在设计阶段,就假设线上系统会出问题,从而在管控系统添加相应措施来防止一旦系统出现某种情况,可以及时补救。面向失败的设计思想的一个基石就是将监控、告警、管控系统作为系统基石的一部分,在设计阶段即融于整体。
-
简单化设计原则:系统架构简单清晰,具备水平扩展能力。与之相反的就是过度设计,如何更好的平衡必要复杂度与意外复杂度是关键;不是在不能添加更多的时候,而是没有什么可以去掉的时候,才能达到完美。
-
监控设计原则:监控系统架构及监控规则应该是简单的,易于理解的。监控项覆盖度高,需要控制好有效报警数,监控围绕四大黄金指标:延迟,流量,错误,饱和度展开。
-
管控设计原则:需避免权限过大,系统应具备逃生能力,灰度能力。线上很多故障发生,都是因为权限过大或者不具备灰度能力导致的。管控系统作为服务提供方,理应当对自身行为带来的危害负责,需要具备自保护能力。
-
敏捷设计原则:敏捷开发,小规模,多批次迭代。敏捷开发对面向失败设计来说可以有效预防,降低故障发生,同时能够快速定位及恢复故障。
-
变更设计原则:可灰度,可监控,可回滚。无论系统发布还是配置项的改动,都需要遵从变更三板斧。线上 60% 故障是由于变更发布导致的,渐进式发布,快速准确检测到问题,同时快速回滚是非常必要的。
-
容量设计原则:基于稳态容量及尖刺容量规划,适当冗余,具备快速弹性扩容能力。通过自然需求增长模型来预测稳态容量,通过适当冗余,流控,快速弹性扩容能力保障非自然需求增长。同时做好周期性压力测试。
-
依赖设计原则:最小化依赖,避免循环依赖,通过异步化,服务降级,限流,隔离等手段控制由于依赖带来的影响面。上下游依赖需要建立基于接口,服务,应用等级别的 SLO,了解更多上下游信息,做好防护手段。
-
自动化设计原则:对重复,人肉的操作尽可能通过自动化来保障操作一致性,提升效率。
-
快恢设计原则:标准化的故障恢复流程,从故障被监控发现开始,人员上线响应,故障定位,恢复等一系列流程是人与系统共同参与的活动。从人的角度需要具备 oncall 能力,快速上线能力,快速登录系统定位处理问题能力,系统需要具备快速报警,回滚,隔离,容灾等能力。