如何打造持续高可靠的 IT 系统
很多在外界看起来似乎因果关系极其明确的事情,在 IT 行业却变得扑朔迷离。以至于网上经常流传上线前需要求菩萨保佑的经典桥段。
当然,IT 人员作为有较高文化素养的科技从业者,一般都是典型的唯物主义者,内心自然对求菩萨保佑的做法嗤之以鼻,但每次上线的忐忑心情却是无论如何也掩饰不住的。
虽然 IT 人员对系统稳定性惴惴不安,如临大敌,但业务要求却没有一丝丝同情和宽容。4 个 9,5 个 9 经久不衰,俨然已成为标准要求。
这难道不是很明显的供需失调吗?难道没有有效的办法塑造一个持续高可靠的 IT 系统吗?
深入各行各业数字化浪潮告诉我们,方法肯定是有的。
系统稳定性公式
这里,我们引入一个公式,即系统稳定性公式。
系统稳定性=fx(设计质量,开发质量,测试质量,可靠性锻造质量,复核系统)
01 设计质量
设计质量主要关注产品设计和技术方案设计的质量。
产品方案质量
主要关注产品功能对风险的兼容程度。假设客户需求是在两座山之间搭建一条通道,实现人两山之间之间通行。产品给的设计方案是考虑到住在山上的人身体好,眼神好,还会点功夫,那就拉一条钢丝绳吧。基于这样的产品方案,哪怕施工人员采用世界上质量最好的钢丝绳,也难以避免有人拉盒饭的宿命。
技术方案质量
技术方案质量则关注地技术方案本身的性能、可靠性、可测试性、可运维性。同样是上述需求,假设产品方案是设计一座桥梁。那么技术方案需要怎么设计呢?山谷的最大风速、两端的岩层硬度、未来出行工具的考虑等等都是技术方案需要考虑分范畴。
还有假设桥梁后续需要检修,有没有额外的通道?下雨天,要不要考虑路滑跌落山谷的风险?
02 开发质量
开发质量对系统稳定性的贡献怎么说也不为过,它是稳定性的基石。不严谨地说,如果某个系统的开发质量非常高,那么后面的几项都是可选项。那么如何提高开发质量呢?
代码审查
代码审查是一项基础的开发活动。通过代码审查,可以发现隐藏再代码中的隐患,及时解决。代码审查的本质是多视角群体智慧的应用。关于代码审查的具体操作介绍太多了,本文不再展开。
静态代码扫描
常见的静态代码扫描工具有 Sonar 以及阿里规约。目的是发现初级的不符合最佳编码实践的代码,提前暴露风险。
单元测试
全备的单元测试,对于保障系统稳定性无疑是可靠的,尤其是对于避免功能退化有很强的预防作用。然后,真正能静下来一以贯之的维护好单元测试的同学实在是凤毛麟角。确实有较大的的因素是项目周期的不可控导致无暇及时编码单元测试,但有志者事竟成。
案例分享和复盘
常态化的案例分享和复盘,是一种经验的传播,可以实现一个人的经验成为群体的经验,从而避免重复问题的频发。譬如在开发团队中,经常出现的问题有:开发新功能而忽略历史数据的处理、配置错误、缓存错误、枚举类型转换错误、缺少并发控制和幂等机制。
完善的自测
虽然这是最基本的要求,而往往却很难达成。不少开发同学寄希望于测试团队保证代码的质量,自己只负责编码代码并编译通过,随便跑一下,没问题就提测了。结果就陷入漫长的发现 BUG-修复 BUG-再发现-再修复的循环中,并且过程中一般开发同学还会有其他任务加入,超出预设的 BUG 修复时间又进一步挤压新任务的开发质量,从而导致恶性循环。
严谨的态度
理论上这是一条放之四海而皆准的可靠性保障因素。没有严谨的态度,会导致一系列出于意料的问题,这时候只能后补流程进行规避。结果是因为不严谨出了问题就补一些流程,过几天又出其他问题又补一些流程,最后,发现流程很多了,还是堵不住因严谨不足带来的事故。这时候,换人是一个方案;加人也许是一个方案,当然不差钱的情况下局部适用。
众观全局的视眼
跟上一点类似,全局观也是做好一件事情的重要且可贵的因素。因为能够众览全局,就可以发现跨团队协作间可能出现的问题;因为有了全局观,思考的广度和深度得到了夸张,方案的全备性也被延伸。
03 测试质量
测试质量是对开发质量的有力补充,但现实地说,很难补全。一般测试期间发现的 BUG 越多,预示着生产上出问题的概率也会更高?何解?这取决于测试的方式。如果只是黑盒测试,一般能验证的只是操作层面和展示层面的逻辑,但是背后的处理逻辑有没有报错不知道,那些没被展示和操作到的地方有没有问题不知道?还有用例的覆盖范围也很关键。那么如何提高测试质量呢?
首先要对开发方案、实现逻辑和数据结构很熟悉。能够框定影响范围,不漏测很关键,并寻找临界点和异常场景进行测试。
其次,要明白一个系统=逻辑+数据,逻辑包括界面展示的可操作性的部分,也包括后台的处理逻辑,所以需要关注日志输出对不对?定时任务执行是否正常?数据也是同理,展示的只是部分数据的部分字段,其他字段的值对不对?另外缓存/MQ 等都是数据,别忘了。
其次,测试覆盖率工具,看看所执行过的用例覆盖了哪些分支,哪些又是法外之地。
再次,一个人的思维是有局限的,因此必要的时候进行交叉测试,尽可能的缩小认知盲区。
最后,及时锚定系统的主流程,哪怕是修复一个文字,也需要对主流程进行事无巨细的回归。
04 可靠性锻造质量
上述三方面质量大家比较熟悉,那么这个可靠性锻造质量又是什么玩意呢?其实他不是什么玩意,而是一种系统工程。利用软件工程来铸造系统质量。
常见的落地方案有以下几种。
压力测试
人为的给系统发送大批量的请求,并持续一段时间,已检验系统在承压下的反应。很多系统一旦持续承压,会出现数据库连接池不足,锁超时,因并发导致的重复处理问题,响应时间过长等等,这些都为接下来的整体性优化提供了真实的指引。
故障演练
即事先找出可能会影响系统稳定性的所有因素,然后假设这些因素的一个或多个出现故障,推演系统可能的反应。之后,进行演习,观察系统的真实表现是否符合预期。一个设计良好的系统,往往估计故障自愈能力,至少是具备可恢复的能力,哪怕是依赖工程师的人为操作进行恢复,如果系统出现数据混乱,且完全是没有预案的那一种,一旦风险应验,那可能是一种灾难。
混沌工程
混沌工程是近几年兴起的一种工程实践。相比故障演练,他会更加的不可预测,包括时间上不可预测,也包括故障点的不可预测,因此更符合风险的不可预知特征。
周期性巡检
巡检是一种主动发现问题的有效手段。通过事先罗列的检查清单,周期性的进行检查,包括主动模拟客户进行体验,可以发现隐而未现的问题。
05 复核系统
最后我们说说复核系统。
其实复核系统更多是一种思想,从它出发,可以采用管理手段上的多重复核,也可以技术手段的复检工具或系统。举个栗子,譬如我们要开发一款税收计算工具,而计算结果非常重要,不容有失。按照复核系统的思想,可以设计结果一致但思路不同的两种方案,只有当两种方案给出的答案是一致时,我们才认可计算结果,系统才能继续流转,否则就暂停并告警。
06 做个小结
诚然,软件系统是一个多因素的复杂系统,代码、配置、数据库、中间件、服务器、若干第三方系统等等共同决定了系统的可靠性,别忘了还有时间这个影身的因素。往往一个系统 3 分开发,7 分打磨,历经 1-3 年才能铸就一套稳定的优良系统。但是软件系统是机械的,自身是不会进化改善的,依赖的还是工程师的智慧。只有加强对质量因素的全面认知,配合以谨小慎微和拒绝侥幸的优良作风,完全是有可能缩短系统稳定性的时间的。
假设同样的赛道,都是等量级的选手,友商的系统还在喋喋不休的找 BUG 打补丁焦头烂额的时候,你的系统历经风吹雨淋而岿然不动,即使遇到极端情况,也可以快速恢复。单单这个考察点上,你是客户你选谁呢?
版权声明: 本文为 InfoQ 作者【异想的芦苇】的原创文章。
原文链接:【http://xie.infoq.cn/article/edc0f24774f168dddf7aef9fc】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论