热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

如何提升系统可用性?

相传魏文王和名医扁鹊之间曾经发生过这样一段对话:魏文王:“你们兄弟三人,谁是医术是最好的呢?”扁鹊:“大哥最好ÿ

相传魏文王和名医扁鹊之间曾经发生过这样一段对话:

魏文王:“你们兄弟三人,谁是医术是最好的呢? ”

扁鹊:“大哥最好,二哥差些,我是三人中最差的一个。”

魏文王:“那为什么你的名气最大?”

扁鹊:“大哥治病,是治病于病情发作之前,病人尚未发病即已根除病因,使得他的医术没有得到认可,没什么名气;二哥治病,是治病于病情初起时,二哥药到病除,大家认为二哥善治小病,名气只在本乡里;而我是治病于病情严重之时,大家看到我或在经脉上穿刺放血,或在患处敷以毒药以毒攻毒,或动大手术直指病灶,使重病人病情得到缓解或治愈,所以以为我的医术高明,名气因此响遍全国。”

在上面这个小故事中,根据医生治病发生在病情发展的不同时期可以分为三个阶段:


  • 病发前,施以小术,代价非常小,却很容易根除病因。
  • 病发初期,患者小恙,对症下药,也能很快治愈。
  • 病情严重,患者身体损伤极大,要施以非常手段才有可能救治病患,代价很大,也很容易留下后遗症。

技术人员治理系统犹如医生治病救人,为了保证系统能够稳定地对外提供服务,有比较高的可用性,需要关注系统发展的整个生命周期,见微知著,一方面能够识别软件开发中潜在的问题,尽早解决;另一方面当系统出现小问题,不要忽视,及时处理;最后当系统发生较大问题时,也能够使用雷霆手段快速恢复,保证系统可用。

为了提高系统的可用性,这三个阶段我们都需要关注,本文会通过分析影响系统可用性的因素,尝试找出在这三个阶段我们需要采取的必要措施。


什么是系统可用性?

首先我们来看看维基百科上对可用性的一些定义:

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

系统可用性是衡量一个系统正确地对外提供服务(可工作)的能力。我们通常采用SLA(Service Level Agreement)来衡量系统可用性,也就是我们经常听到的的几个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个小时进行只读的关键场景回归测试,成本非常高昂),这导致定期的版本发布经常会带来一些意外的故障,每次发布后都需要有人值班来解决这些故障。

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


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

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

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


  • 硬件故障
  • 网络故障(包括网络带宽不足导致的通信问题等)
  • 系统升级(操作系统、数据库、网络设备、中间件等)
  • 日常维护(备份、迁移等)

如何提高系统可用性

影响系统可用性的因素很多,以上列举了一些非常典型的场景,这足以让我们对影响可用性的因素有一个非常直观的理解。为了从可实施的角度讨论如何提高系统可用性,这里不考虑基础设施硬件故障等不可控因素。

从上面的因素中我们不难发现,有些问题我们可以通过提高工程化能力和优化工作流程解决,但如何将这些工程化能力和流程落地也是一个非常复杂的问题,因此我下面会通过技术和团队两个视角来看如何才能提高系统的可用性。


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

如何提升系统可用性?

 

根据可用性的定义,要提高系统的可用性,就是要缩短系统不可用的时长,保持系统的健康状态;那么回顾下文章开头的小故事,我们可以从三个阶段来针对性的采取一些措施:


  • 病发前:
    • 完善的代码质量管理体系和自动化测试体系,能够保证产品质量,通过代码检查、安全扫描和测试自动化,避免未经测试的代码部署到生产环境
    • 完善的权限管理体系,能够保证生产环境权限不滥用,避免过多的人为操作对生产环境产生影响
    • 其他自动化的开发、运维工具体系,在提高工作效率的同时,注重安全性,通过自动化的脚本检查、运维流程自动化等方式避免不必要的错误对生产环境造成的危害
  • 病发初期
    • 完善的监控体系,能够尽早识别系统的潜在问题,系统运营人员可以快速甄别即将发生的故障,不要等到用户反馈才知道系统出了问题
    • 完善的持续集成/持续部署体系,能够保证尽量快的反馈,尽量短的发布时长,在功能开发和故障修复后快速地部署代码到生产环境
  • 病情严重
    • 完善的发布验证、回滚、限流、熔断、降级策略,能够尽量缩小故障的影响范围,保证即便有部分服务不稳定,也不至于导致整个系统不可用
    • 完善的灾备恢复体系和演练,能够保证系统在发生重大紧急事故时可以快速恢复,尽量缩短不可用时长

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

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

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

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


  • 自上而下崇尚技术,尊重技术
  • 有专家级成员,有能力实施上面提到的各种工程能力
  • 不急功近利,不会为了短期的业务目标而在技术上妥协
  • 团队成员遵守团队纪律,不做违反纪律,破坏规则的事情

结语

追求系统的高可用就像一个人追求身体健康一样,整个软件开发团队自始至终都要秉持爱护软件系统的心态,在软件开发的全流程中,时刻保持警惕,通过提高团队在三个阶段中的工程化能力来及时发现和解决系统中存在的问题。

这不单纯是个技术问题,善治系统的团队首先要在团队内建立尊重技术、工程的文化氛围,建立团队行为规范,严明纪律,有所为有所不为;在此基础上,不断在团队开发过程中针对问题寻找解决问题的最佳实践,做且做好正确的事,相信高可用是必然的结果。


推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文探讨了容器技术在安全方面面临的挑战,并提出了相应的解决方案。多租户保护、用户访问控制、中毒的镜像、验证和加密、容器守护以及容器监控都是容器技术中需要关注的安全问题。通过在虚拟机中运行容器、限制特权升级、使用受信任的镜像库、进行验证和加密、限制容器守护进程的访问以及监控容器栈,可以提高容器技术的安全性。未来,随着容器技术的发展,还需解决诸如硬件支持、软件定义基础设施集成等挑战。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 本文介绍了PhysioNet网站提供的生理信号处理工具箱WFDB Toolbox for Matlab的安装和使用方法。通过下载并添加到Matlab路径中或直接在Matlab中输入相关内容,即可完成安装。该工具箱提供了一系列函数,可以方便地处理生理信号数据。详细的安装和使用方法可以参考本文内容。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
author-avatar
香福武燕_205
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有