从故障处理谈如何提升系统可用性

什么是系统可用性?

说到故障处理,大家一定不陌生,长期维护的系统或多或少都会经历线上的故障。通常来说,线上的故障会导致系统的可用性降低,那么什么是系统的可用性呢?我们来看维基百科上对可用性的一些定义:

CAP定理中定义的可用性(Availability):每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据

可用性就是一个系统处在可工作状态的时间的比例

通过上面的定义可以看出,系统可用性是衡量一个系统正确地对外提供服务的能力。

生产环境故障通常会依据影响的紧急程度和范围进行优先级划分(P1、P2、P3……),事故优先级越高,业务影响越大,紧急程度越高。然而,并不是所有级别的故障都会对系统可用性产生影响,一般情况下导致主业务流程无法正常工作的故障才会参与可用性的计算。

系统可用性通常采用SLA(Service Level Agreement)来衡量,简单可以理解为系统处于可用状态的时间比例,也就是我们经常听到的的几个9,其对应的系统不可用时间可以参照下表:

系统可用性% 不可用时间/年 不可用时间/月
90% 36.5 天 72 小时
99% 3.65 天 7.20 小时
99.9% 8.76 小时 43.8 分
99.99% 52.56 分 4.38 分
99.999% 5.26 分 25.9 秒

3个9(99.9%)表示一个月最多不超过43.8分的不可用时间,对于每月例行停机维护的系统基本很难达到;5个9(99.999%)要求一年内系统不可用的时长不超过5分钟,听起来就觉得不可思议。

哪些故障会影响系统的可用性

故障是不可避免的,除了人为原因导致的故障,基础设施的定期维护,硬件设备损坏,自然灾害等等都会导致系统不可用,因此100%的系统可用性是基本不可能达到的;要提高系统可用性,我们得先分析故障发生的原因和影响,下面根据我的经验列举一些会对系统可用性产生较大影响的故障:

人员误操作

经典如rm -rf . /的操作在日常的开发过程中并不少见,比如:

  • 在生产环境执行了IDE导出的数据脚本,选中了DROP TABLE,结果删除了整表的数据

  • 在生产环境中清理冗余的Docker镜像文件时,不慎删除了所有镜像

  • …… 数据、文件存储等无疑是大多数企业的核心资产,涉及到数据的故障往往都是非常大的故障,不紧影响范围非常大,如果前期没有足够的灾备准备,是很难在短时间内恢复的,甚至可能无法恢复,造成巨大损失。

雪崩效应

在分布式系统架构下,服务之间需要配合来完成复杂的业务流程,某个服务提供者的不稳定在请求量变大的情况下,会逐步演化成整个系统的雪崩效应。

雪崩效应通常会经历如下过程:

  1. 服务提供者不可用(宕机或性能较差)

  2. 服务调用者请求量增加(业务量增加、失败重试、缓存穿透等)

  3. 服务调用者系统资源耗尽,服务调用者不可用

雪崩会造成整个系统的瘫痪,以我们的系统曾经经历了一次雪崩为例,一个核心服务在没有代码变化的情况下,增加了用户量(可以理解为对用户分批开放),在数据基数增大和请求量增大时,服务的接口性能无法满足需求,陡增的请求量对数据库了造成非常大的压力(CPU占满),接口全部超时,导致长时间占用API Gateway的连接资源,API Gateway无法处理其他请求,进而导致了整个系统的瘫痪,如下图:


本质上来讲雪崩的发生是因为服务提供者无法满足当前业务的高并发需求,同时也没有很好的应对措施保证系统其他服务的正常运转。

未经完整测试的版本发布

以上两类故障的发生通常会引发非常严重的问题,但频率相对较低,而定期的版本发布常常因为没有经过完整的测试导致线上故障发生,严重的情况下也会对可用性产生很大的影响。

随着系统服务年限的增长,业务的增长让系统变的越来越复杂,依赖人工的黑盒测试基本上很难覆盖所有业务场景(我们曾经有一个开发了3年多的系统,在没有自动化回归测试的情况下,每次发布后需要4个测试同学花费2个小时进行只读的关键场景回归测试,成本非常高昂),这导致定期的版本发布经常会带来一些意外的故障,每次发布后都需要有人值班来解决这些故障。

系统间集成测试成本更高,一方面集成测试需要跨多部门进行沟通协调,另一方面集成的一方通常无法知道另一方的实现细节,测试用例很难保证全面。对于关键系统的集成,如果修改后没有充足的回归测试,上线后很可能导致影响主流程的故障,影响用户的使用。

基础设施故障及定期升级维护

不管是自建基础设施,还是使用第三方云服务,基础设施的故障和定期升级维护是不可避免的,也是影响系统可用性的关键因素。

影响可用性的基础设施相关因素包括:

  • 硬件故障

  • 网络故障(包括网络带宽不足导致的通信问题)

  • 系统升级(操作系统、数据库、网络设备、中间件等)

  • 日常维护(备份、迁移等)

如何提高系统可用性

根据可用性的定义,要提高系统的可用性,就是要缩短系统不可用的时长;从故障处理的角度来思考:

  • 在故障发生前,尽量避免故障发生

  • 在故障发生后,快速使系统恢复

这两句话说起来简单,实际做起来确未必,即便要做到3个9的可用性,每月40分钟的不可用时长,试问有多少系统可以严格满足这个要求?从上面的故障分析来看,这不仅仅是个技术问题,更是一个团队如何看待生产环境,如何看待自己开发出来的系统的问题。

从技术视角,要不断强化工程能力

要做到在故障发生前快速识别,在故障发生后快速恢复,没有强大的系统化工程能力是无法做到的;针对前面对故障的分析,要提升系统的可用性,我觉得需要加强的工程能力如下:

  • 完善的代码质量管理体系和自动化测试体系,能够尽量保证产品质量

  • 完善的监控体系,能够尽早识别系统的潜在问题

  • 完善的持续集成/持续部署体系,能够保证尽量快的反馈,尽量短的发布时长

  • 完善的发布验证、回滚、限流、熔断、降级策略,能够尽量缩小故障的影响范围

  • 完善的权限管理体系,能够保证生产环境权限不滥用

  • 其他自动化的开发、运维工具体系,能够尽量避免通过人工方式对生产环境进行干预

从团队视角,要有一支重视技术的团队

在软件系统的开发运维过程中,我们有很多手段可以发现问题,如线上故障、监控报警、回顾会议等等,但从根本上解决问题往往非常困难,大多数情况下是头痛医头,脚痛医脚,到最后结果就是技术债台高耸,线上故障频发。

探究其原因,可能比较复杂 ,但从团队视角来看,通常存在团队对待技术并没有那么严谨,对待生产环境没有那么敬畏,对待自己的代码没有那么严苛。

要提升系统的可用性,必须要有一支重视技术的团队,这个团队应该具备以下特征:

  • 自上而下崇尚技术,尊重技术

  • 有专家级成员,有能力实施上面提到的各种工程能力

  • 不急功近利,不会为了短期的业务目标而在技术上妥协

  • 团队成员遵守团队纪律,不做违反纪律,破坏规则的事情

结语

相信大家都听过扁鹊三兄弟的故事,魏文王曾求教于名医扁鹊:“你们兄弟三人,都精于医术,谁是医术最好的呢? ”,扁鹊回答说:“大哥最好,二哥差些,我是三人中最差的一个。”,魏文王不明其理,便问扁鹊:“那为什么你的名气最大?”,扁鹊解释道:“大哥治病,是治病于病情发作之前,病人尚未发病即已根除病因,使得他的医术没有得到认可,没有名气;二哥治病,是治病于病情初起时,症状上不明显,二哥药到病除,大家认为二哥善治小病,名气只在本乡里;而我是治病于病情严重之时,大家都看到我在经脉上穿刺,用针放血,或在患处敷以毒药以毒攻毒,或动大手术直指病灶,使重病人病情得到缓解或治愈,所以以为我的医术高明,名气因此响遍全国。”

追求系统的高可用性犹如治病救人,在故障频发时快速处理故障确实能彰显团队技术能力,但系统很可能已经病入膏肓;善治系统的团队应该在一开始就着手各种最佳工程实践的实施,在团队内建立尊重技术、工程的文化氛围,建立团队行为规范,严明纪律,次为上策也。

你可能感兴趣的:(从故障处理谈如何提升系统可用性)