摘要:随着社会的发展,分工的精细化及协同的规模化趋势越来越明显,互联网行业高速发展及云时代的到来,IT行业同样也在经历着这个过程。在这个背景下,软件架构也发生了一系列变化,从面向功能的单一系统架构,分布式架构,到面向业务的中台化架构,到现在的面向生态的云化架构。那么架构演进的过程中,软件架构思想是否需要做些演进及变化呢?特别是在云的时代,答案当然是肯定的。云意味着开放,意味着生态,意味着协同,同时也意味着更多的不可控。因此在云时代,传统软件架构思想原则基础上,面向失败的架构设计也愈发越来越重要。Design For Failure Is Key To Success In The Cloud.
什么是面向失败的设计?
面向失败设计,每个人都有自己的解读,你可能会说我在设计系统的时候也会考虑稳定性,性能,容量等,也是面向失败的设计,这个显然没有正确理解面向失败的设计。从面向对象角度来看,这还是面向功能或者业务视角的,是功能的性能,功能的容量,功能的稳定性。面向失败的设计,就是以“失败”为对象,天然为了失败而存在的设计思想,同时贯穿于软件整个生命周期。举个具体的例子,我们经常在系统上线后,才会去添加相关的监控项,或者认为功能不会有大风险而遗漏了监控项,在系统出了故障以后才意识到需要在管控系统添加相应措施来防止一旦系统出现某种情况,可以及时补救。如果有人告诉你,系统上线50%概率会出现问题,可能你在设计阶段就会考虑添加监控项了。面向失败的设计思想认为监控及管控分别是系统的眼睛和手,系统最重要的组成部分,设计阶段应该要考虑进去,而现实中我们往往更多的精力都放到了躯体的建设上了。另外双11其实就是一个面试失败设计的经典案例。
面向失败设计原则
软件如同人一样,在孕育及成长过程中,受先天基因及后天成长环境影响,都会遇到不同程度影响生命安全的问题,小时候我们都打过预防针,这是一种对于已知的确定性风险的防范, 我们通过锻炼身体来抵御未知不确定性的风险。同样在软件
生命周期中,受到先天架构以及后续持续版本迭代发展的影响,也会出现各式各样的问题,我们需要通过面试失败的设计,贯穿整个软件生命周期来防范已知的确定性风险及未知的不确定性风险。
架构设计阶段:
简单化设计原则: 系统架构简单清晰,具备水平扩展能力 。与之相反的就是过度设计,如何更好的平衡必要复杂度与意外复杂度是关键。“不是在不能添加更多的时候,而是没有什么可以去掉的时候,才能达到完美”。
监控设计原则:
监控系统架构及监控规则应该是简单的,易于理解的。监控项覆盖度高,需要控制好有效报警数,监控围绕四大黄金指标:延迟,流量,错误,饱和度展开。
管控设计原则:
需避免权限过大,系统应具备逃生能力,灰度能力。线上很多p1级故障发生,都是因为权限过大或者不具备灰度能力导致的。管控系统作为服务提供方,理应当对自身行为带来的危害负责,需要具备自保护能力。
开发发布阶段:
敏捷设计原则:敏捷开发,小规模,多批次迭代。敏捷开发对面向失败设计来说可以有效预防,降低故障发生,同时能够快速定位及恢复故障。
变更设计原则:
可灰度,可监控,可回滚。无论系统发布还是配置项的改动,都需要遵从变更三板斧。线上60%故障是由于变更发布导致的,渐进式发布,快速准确检测到问题,同时快速回滚是非常必要的。
运行运维阶段:
容量设计原则:基于稳态容量及尖刺容量规划,适当冗余,具备快速弹性扩容能力。通过自然需求增长模型来预测稳态容量,通过适当冗余,流控,快速弹性扩容能力保障非自然需求增长。同时做好周期性压力测试。
依赖设计原则:
最小化依赖,避免循环依赖,通过异步化,服务降级,限流,隔离等手段控制由于依赖带来的影响面。上下游依赖需要建立基于接口,服务,应用等级别的SLO,了解更多上下游信息,做好防护手段。
自动化设计原则:
对重复,人肉的操作尽可能通过自动化来保障操作一致性,提升效率。
快恢设计原则:
标准化的故障恢复流程, 从故障被监控发现开始,人员上线响应,故障定位 ,恢复等一系列流程是人与系统共同参与的活动。从人的角度需要具备oncall能力,快速上线能力,快速登录系统定位处理问题能力,系统需要具备快速报警,回滚,隔离,容灾等能力。
以上是我对面向失败设计的一些思考,也参考了google sre相关书籍,期望能抛个砖,引发大家更多的参与到对于面向失败架构设计中来,为我们的安全生产保驾护航。