报警不响,黄金万两的“稳定性成熟度”干货
1. 什么是稳定性
稳定性指在应用变化,外界和环境变化,以及随着时间推移下,应用可以正常稳定的提供服务。
停留:怎么去保证你的服务尽可能停留在100%。
偏离:如果偏离100%,如何让它恢复的足够快。
可以把中间件服务、MQ、ZK 等当做一个服务。
可以把资源型服务、MySQL、MongoDB、Redis 等当做一个服务。
3.
上面列举了5类问题,基本上囊括了影响服务稳定性的所有因素,我们可以通过以下6个手段全面的解决以上问题。
包括:研发管理、变更管理、隔离、冗余、容错容灾和演练。
▌3.1.隔离
隔离的手段
把经常变化和不变的分开,把重要的和不重要的分开,把核心的和非核心的分开。
把消耗CPU的和消耗内存的分开,把用户接口和后台接口分开,总之隔离就是要区分核心和非核心,稳定和不稳定。保障核心服务的稳定性,避免相互影响。
隔离的手段
一般通过解耦,异步化来达到隔离的目的。
隔离解决的问题
隔离划分
例子
运行时隔离:比如慢SQL,比如热点隔离(全部资源中部分资源高频率使用)。更典型的就是线程隔离,一个性能较低的服务会“霸占” 容器中绝大多数线程,而其它性能正常的服务的请求则需要等待线程资源的释放。最后,整个容器会崩溃,Hystrix的舱壁模式就是为此而生,运行时隔离线程。
进程隔离:比如运营使用的后台系统API 和 用户使用的API接口,因为变更频率,稳定性要求,请求量完全不一样,我们常常把他们分开部署到不同的进程中,达到进程隔离的目的。
机器隔离:比如当前需要上线一个秒杀系统,并发量很高。那么他就不能和核心服务放在一起,甚至不该和任何其他正常服务放在一起(进程隔离)。部署的时候也应该和核心服务的机器分开开部署。再比如在一台机器上同时存在两个一样的CPU密集(IO密集)型服务应该分开,或者CPU密集和IO密集部署在一起的也应该分机器部署,理由是把一台机器的某个性能或者多个性能用到极限,一旦需求变更上线,场景变更,变数是不可控的。同时这样的机器和系统也经受不起波动和突刺的冲击。
▌3.2冗余
隔离之后,我们可以排除掉大部分不稳定因素,保证核心服务的稳定性,但是当核心服务本身和所在的环境出现问题,隔离就没有办法解决了。
定义
冗余解决的问题
核心服务本身出现问题和部署环境变化时的稳定性应对,比如服务故障、网络故障、机房故障等。
冗余的手段
当故障发生时,通过流量调度机制,切换流量到正常节点和环境。
冗余要求
可独立部署:可以直接在运维平台打包部署,而不需要依赖其他服务部署完成后才能部署运行。
无状态:服务设计时候,需要保证服务是无状态的,可以随时水平扩展。
无依赖:为了尽量避免冗余同时失效的情况,冗余副本之间需要相互独立,完全对等,不能相互依赖,机房内副本跨交换机部署,如果有多机房冗余的情况,各机房独立,不能有完全相同的依赖。
自动化:需要支持灵活的流量调度策略,包括负载均衡,服务发现,流量路由等。当节点故障时,通过健康检查,故障节点剔除、动态路由切换等机制,可以平滑自动的地将流量从故障节点切到冗余节点,保证故障不会扩散和不会影响系统整体稳定性。
冗余级别
冗余细分其实也可以分为资源冗余和应用冗余,或者软件冗余和硬件冗余,这里我就按照服务粒度来统一划分。
同机房冗余N+2,如果一个服务需要 1 个实例正常提供服务,那么应该部署 1 + 2 = 3 个节点。如果是N+1发布的时候就失去作用了。如果一个服务需要10个实例正常提供服务,同时部署了 10+2 =12个节点,代表此服务最多容忍2个节点同时出现问题,如果超过2个节点同时出现问题就无法正常响应所有请求。
集群级别和机房级别的冗余需要保证,当 “1”挂了,剩余 N 可以承接住所有流量,提供正常服务。
容灾容错定义
容灾容错解决的问题
解决手段
例子
限流例子:随机拒绝请求、拒绝低优先级系统调用,拒绝低级别用户调用,根据白名单或黑名单规则拒绝特定用户请求调用,对失败率高或响应超时系统调用拒绝调用,利用线程池队列排队处理调用,拒绝超出处理能力调用等
降级例子:功能禁用(功能降级)。使用本地缓存而不是调用外部服务、不调用下游依赖服务(上游接口降级)。个别接口消耗大量资源的停用接口(接口降级)。非核心服务消耗大量数据库资源停用服务(服务降级),服务异常时采用默认数据或兜底数据,同步变异步调用,减少定时任务执行频率或减少业务峰值时间定时任务的执行等。
▌3.4 研发管理
服务的稳定性有先天性,先天性是在项目开发过程中就被决定的。项目研发,是一个多方交互、多阶段、长时间的一个过程。在研发过程中,需要通过制度和规范,过滤和减少出错。同时每一个阶段每一个点,又可能是一套庞大的体系。
比如代码开发中《编码规范》、《POM依赖规范》、《中间件使用规范》等展开都是一大片。
解决问题
解决服务本身问题,包括代码质量、逻辑质量、架构设计质量、稳定性设计质量等。
研发过程
▌3.5 变更管理
解决问题
解决因为变跟而引起的问题。
变更划分
服务变更,配置变更,数据变更,环境变更。
要求
例子——反面的教材库
代码搭车上线:比如由于缺乏有效的代码修改管理机制,某产品线由于代码搭车上线,出现过多次线上故障,并且由于变更时涉及的修改比较多,导致问题定位和追查时非常困难。
服务回滚时遗漏回滚代码:某业务功能上线时,有bug,发现后马上回滚了服务,但是代码没有回滚,第二天其它功能上线时候,带上了此代码上线,导致服务再次异常。因此,服务回滚之后,必须第一时间回滚代码,保证主线代码任何时候都是干净没有问题的。
服务上线预发之后未上线到生产:某业务代码合并到master之后,上预发验证时间过长一直停留在预发。后续业务变更在不知情情况下,继续合并到master,预发验证之后,带着上一版本一起上线到生产。由于上一版本的线上配置不全,业务未验证。导致上线之后报错。因此针对代码分支管理一定要有master lock 规范。
服务启动或者回滚时间过长:某服务上线异常,回滚时单个服务回滚时间太长,导致未能短时间内快速止损。经排查,回滚过程中部署服务都存在耗时过长的现象,由于服务回滚速度比较慢,产生了较大的线上服务故障。定期检查和优化服务的启动和回滚时间,保证出现故障时可以第一时间完成回滚操作。
配置文件缺少有效的校验机制:配置文件由模型产出,数据配送系统实时配送到线上服务,模型产生的配置文件有问题,引发线上故障。因此,针对配置文件,尤其是策略模型产出的配置文件,需要建立严格的检查和校验机制。
缺少索引:某服务业务变更,新增/修改 sql语句,上线之后,在业务高峰期,服务过载,响应变慢。经排查新sql 没有走索引,导致sql耗时增加,服务响应变慢,吞吐量降低。因此涉及大表,SQL改动,code review 时候,一定要检查索引,评估SQL响应时间和业务的请求量。
小流量后的修改没有经过严格的测试和灰度验证:某服务经过小流量灰度后,代码又有少量修改,再次上线时未灰度,导致线上故障。再小的变更,都要进行测试、灰度和双重检查。修改一行代码,也可能导致线上的稳定性故障。
▌3.6 演练
通过以上的5项手段,我们可以一一解决之前列出的影响系统稳定性的5个因子。但是在故障发生以前,我们依然无法校验系统的稳定性。也不知道上面所采取的措施那些存在隐患,以及当前的系统可以正常服务多大规模流量,多大流量该限流,多长时间该超时等,我们都不知道。所以我们需要演练。
演练解决的问题
演练的手段
放火/压测:在生产环境,通过模拟故障,模拟流量请求检测我们的稳定性,和发现遗漏的隐患。以达到优化系统稳定性的目的。
划分
4.
怎么建设
以上6个手段,或者说只是6个分类。虽然基本囊括了所有解决问题途径,但也仅仅只是个分类,没有实际解决我们项目中遇到的问题。
那么有了这6个手段(分类)之后,我们该如何去建设我们解决手段的框架呢?
▌4.1 体系化
使用类比,解决问题的手段是一个完整的整体,解决方法有六大分类即6个面,每一个分类里有无数的关键项组成即线,每一个关键项都有很多的关键点组成即点。
我只需要按照每一个分类找出那些关键项,慢慢建设一个个关键点就可以一步去步完善解决问题的体系。
例子一
面:研发管理
点:(1)公共API必须使用BOM 管理;(2)线上API 必须使用RELEASE;(3)新版本迭代只修改顶层POM中的版本。
例子二
面:变更管理
线:《回滚规范》
点:
如:某个变更删除了数据,直接回退数据没了。办法:分成两半。第一半禁止访问这个数据,发布验证没问题之后,再发布第二半真真删除数据。
稳定性的本质是来自于,无数的踩坑血泪史,然后想出的一系列解决办法。而不同的服务形态,阶段不同,导致的踩坑不一样。而众多的服务又存在很多相似采坑经历。
所以拿出那些可以达成共识的,重要的,必须的作为统一的规范,然后准许不同的业务服务制定自己独特的标准和办法,达到留同存异的目的。
然后我们得出以下稳定性手段优劣的评判
5.
怎么描述
▌5.1 业务可用性
所谓业务可用性即系统正常运行时间的百分比
故障时间=故障修复时间 - 点故障发现(报告)时间点 服务年度可用时间% =(1 - 故障时间/年度时间)× 100%
▌5.2 故障的度量
故障权重
关于响应时间
展示耗时取决于设备差异,前端代码。
应用处理耗时就是,请求的服务端响应时间,也是我们关注的重点。
用户响应时间
有追求的用户响应时间
应用处理耗时
有追求的应用处理耗时
▌5.3 服务分类
我们需要根据业务重要程度,影响面大小,去划分我们的服务。
6.
怎么划分
▌6.1 阶段划分 衡量系统适用于,或者需要达到那个稳定性阶段,取决于请求量和业务的重要性,与投入产出比。 请求量:一般来说请求量就是对系统最大的外界影响。不同的请求量下,对系统的架构,技术的选型,稳定性的要求完全是不一样的。 换句话说,如果你的请求量没达到一定级别,很多稳定性的手段是没用或者收益很小的 业务重要性:你的业务重要性,也决定了我们对这个系统稳定性的定位。 投入产出比:普遍来说越低级别投入资源,技术,人力越低,产出越高。 高一级的实现,必须在低一级已经实现的基础上。
▌6.2 强弱划分
每一个阶段都有完整的上述6中解决手段(即六个面),但是每个阶段中,对每种解决手段(面),解决手段的关键项(线),关键项的关键点(点)需求都是不一样的
我们以:高一级继承低一级,高一级补充或加强低一级,为强弱原则。
7.
成熟度模型
贾正荣