报警不响,黄金万两的“稳定性成熟度”干货
作者:贾正荣
本篇文章基本的思路是,就稳定性列举出需要解决的问题,然后列举出各种问题的解决手段,最后划分稳定性的阶段,不同的阶段对应上不同的解决手段。最后推导出一个稳定性框架——稳定性成熟度。期望在一定范围达成共识,一起推进稳定性的建设。
1.
什么是稳定性
稳定性指在应用变化,外界和环境变化,以及随着时间推移下,应用可以正常稳定的提供服务。
停留:怎么去保证你的服务尽可能停留在100%。
偏离:如果偏离100%,如何让它恢复的足够快。
2.
需要解决什么问题
可以把中间件服务、MQ、ZK 等当做一个服务。
可以把资源型服务、MySQL、MongoDB、Redis 等当做一个服务。
可以把所有本服务所需要的外部服务全部 “抽象” 成下游服务。
在以下因素的作用下,会影响系统的稳定性。
3.
怎么解决
上面列举了5类问题,基本上囊括了影响服务稳定性的所有因素,我们可以通过以下6个手段全面的解决以上问题。
包括:研发管理、变更管理、隔离、冗余、容错容灾和演练。
▌3.1.隔离
隔离的手段
把经常变化和不变的分开,把重要的和不重要的分开,把核心的和非核心的分开。
把消耗CPU的和消耗内存的分开,把用户接口和后台接口分开,总之隔离就是要区分核心和非核心,稳定和不稳定。保障核心服务的稳定性,避免相互影响。
隔离是在架构设计和服务部署的时候就该考虑的问题。
隔离的手段
一般通过解耦,异步化来达到隔离的目的。
隔离解决的问题
核心和非核心,稳定和不稳定隔离开来。
隔离划分
需要先划分出你的最小核心MVP和非核心系统。这个是最重要的隔离,也是后续隔离的前置条件。
例子
运行时隔离:比如慢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 可以承接住所有流量,提供正常服务。
所以 +2 或者 +1 代表的都是 最小冗余数量,表示最多可以承受同时出现问题的 服务/机器/集群/机房 数量。
而为何会有最少+2 和+1 的不同 是因为成本的区别太大。
▌3.3 容灾容错
通过隔离解决非核心服务对核心服务的影响,通过冗余我们解决了核心服务和其部署环境不稳定的影响。
但是当上游突发大流量,异常输入,下游异常,和服务本身异常的时候。系统还是可能被击垮。
容灾容错定义
广义上讲,隔离、冗余都属于容灾。
容灾:面对外部输入(上游)的变化,有一套完整的应对办法,保证核心服务可以持续稳定提供服务。
容错:服务本身要有容错设计,服务对依赖的下游要为失败而设计。
容灾容错解决的问题
容灾:解决上游输入变化时的稳定性问题,比如:突发大流量、异常请求、安全攻击等。
容错:解决服务本身异常和下游服务异常,比如服务内部出错、异常,服务处理延迟,服务处理过载,超时,服务依赖链中部分依赖SLA不达标,造成整体服务不可用,服务链条过长,造成SLA整体不可控等。
解决手段
例子
限流例子:随机拒绝请求、拒绝低优先级系统调用,拒绝低级别用户调用,根据白名单或黑名单规则拒绝特定用户请求调用,对失败率高或响应超时系统调用拒绝调用,利用线程池队列排队处理调用,拒绝超出处理能力调用等
降级例子:功能禁用(功能降级)。使用本地缓存而不是调用外部服务、不调用下游依赖服务(上游接口降级)。个别接口消耗大量资源的停用接口(接口降级)。非核心服务消耗大量数据库资源停用服务(服务降级),服务异常时采用默认数据或兜底数据,同步变异步调用,减少定时任务执行频率或减少业务峰值时间定时任务的执行等............
更多内容,请扫码或长按下方二维码阅读原文
版权声明: 本文为 InfoQ 作者【滴滴普惠出行】的原创文章。
原文链接:【http://xie.infoq.cn/article/75f5d37bc70b910b04c2b35dd】。文章转载请联系作者。
评论