稳定性工程

【安全生产指南一-单点故障】

杜绝单点故障:单点故障是指系统中一旦失效,就会让整个系统无法运作的部件。从架构上来说是一种典型的系统性风险,因为如果系统存在单点,即使系统的其它部分做得再完备,也无法降低单点故障造成的破坏性,因此单点故障出现必然导致整体故障。无论是应用服务器还是底层网络、存储,应该尽量避免出现单点故障。

【最佳实践】

遵循高可用架构设计,做好软硬件冗余架构,在故障出现时能够及时切换。

定期对单点进行巡检、迭代优化。

通过故障注入来发现系统中潜在的单点故障。

【安全生产指南二-负载均衡】

负载不均负载均衡是用来在多个计算机、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到最优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的。使用带有负载平衡的多个服务器组件,取代单一的组件,可以通过冗余提高可靠性。

【最佳实践】

设计流量分配方案时,一定要注意集群负载是否均衡。当部分集群或服务压力过大时应具备水平扩展的能力。

如果业务会出现热点,可以采用分桶或者热点缓存的方案来规避,尽量把热点请求分散到多台服务器上。

要注意负载均衡器自身是否会成为瓶颈,包括容量和高可用的部署。

【安全生产指南三-无状态】

服务状态有状态 (Stateful) 和无状态 (Stateless) 是服务设计的两种模式,首先我们来看看两者的定义:无状态服务对单次请求的处理,不依赖其他请求,也就是说处理一次请求所需的全部信息,要么都包含在这个请求里,要么可以从外部获取到(比如说数据库或缓存),服务器本身不存储任何信息。无状态服务典型的例子就是HTTP协议,它的每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据。

【最佳实践】

在分布式系统的设计中,需要考虑系统的可扩展性需求,尽量规避有状态设计。

不要将IP、磁盘路径(OS不同分隔符及路径读写权限不同)写死在代码或者配置里面。

本地磁盘只写日志,不存储业务相关数据。

【安全生产指南四-监控】

【最佳实践】

1.在系统设计之初就设计好监控,而不是事后再补。

2.监控需要覆盖基本的系统指标监控(如CPU,Memory,Load,JVM,QPS,RT...)及核心业务指标监控

3.同时,这些指标需要有同环比的视图,来借此发现性能或容量的问题。

4.核心业务指标监控是站在业务视角,为系统所提供的商业服务做监控,如系统的下单成功率、购物车转化率、GMV等。同样这些核心业务指标需要有同环比的监控、如果有业务指标的同环比异动、可以在第一时间报警给相关技术团队进行排查定位。

【安全生产指南五-变更回滚】

1.架构演进的过程中,架构的调整升级不可避免。如从单体应用升级到SOA架构,或者从SOA架构升级到微服务架构。为了避免新架构升级过程中带来的系统性风险,系统变更应该具备可回滚的能力,以此来预防故障出现时定位解决问题造成的长时间业务不可用,故障出现时第一时间回滚即可。

2.系统变更的回滚能力应该作为系统升级中很重要的一部分体现在技术方案设计文档中,并在上线前进行严格review。一般对于应用的发布变更,变更系统都会提供回滚到某个版本的能力。

【最佳实践】

1.不要盲目自信,升级过程中要保证所有的线上变更都有回滚方案,故障出现时第一时间先回滚相关变更。

2.回滚能力应该作为系统升级中很重要的一部分体现在技术方案设计文档中,并在上线前进行严格review。

【安全生产指南六-降级】

当系统访问量激增、性能急剧下降或者非核心服务影响到核心服务的响应时,为了保证主流程的高可用,对非核心流程或非核心服务进行降级。服务降级的核心思路即通过对部分非核心页面和服务的有策略不处理(暂停处理或延时处理)来释放服务器资源保证核心流程的正常或高效运作。常见于故障出现时的应急操作或大促高峰期对弱依赖的解耦。一般来说降级通常都是有损的,

服务降级的四种实现思路:

1.开关服务:统一的开关服务将各种服务降级预案统一管理,当出现故障或者业务需求需要降级时,则在开关服务管控平台上操作对应的开关进行服务关闭打开。而开关的统一管理也有利于经验和系统信息的传承,当系统开发负责人不在岗时,其他人也可以通过统一的开关服务管理平台来全局了解系统中的开关信息。

2.预案服务:将开关服务、配置服务等其他降级方案组合成预案统一管理,典型的场景如电商平台进行促销活动时,需要有多个开关及配置在大促时做修改,此时就可以将这些服务组合成一个针对性的预案,在适当的时候操作预案启用和恢复即可。

3.限流降级:限流降级的主要目的是防止系统高负荷运行,保证资源的有效利用。当系统访问量过大或出现突发流量的时候,瞬间的大规模请求可能会超过系统的最大承载能力而导致系统雪崩。这种情况一般通过限流来保障系统核心服务可用,通过局部不可用来交换全局可用。

4.熔断:熔断一般作用在客户端,当客户端与服务端的通信在一定的时间窗口内达到一定阈值时则执行熔断策略(可以换服务列表中的其他节点重试或进入队列),同时采用异步线程探测服务是否恢复可用。当服务恢复可用时则恢复调用链路。

【最佳实践】

1.系统设计时需要针对强弱依赖做甄别,弱依赖不可用不能导致整个系统崩溃。同样,系统作为服务提供者也需要保证客户端的异常请求不能打垮自己。以上提到的降级措施可以根据场景不同选择使用。

2.开关、预案需要沉淀起来,并选择适当的时机对开关及预案的可用性做演练,做好高可用文化的传承。

【安全生产指南七-隔离】

隔离是指当系统发生故障时,能够将故障的影响范围限定在一定范围,是一种有效限制爆炸半径的策略。通过将系统和资源隔离的方式,一方面可以防止故障发生时影响传播,另一方面可以减少资源竞争。常见的隔离方案有动静资源分离、线程(池)隔离、进程隔离、集群(分组)隔离、机房(包含逻辑机房)隔离,租户隔离等

1.线程隔离主要是线程池的隔离,线程隔离需要我们对应用的请求进行分类,不同的任务交给不同的线程池处理。比如隔离核心线程池和非核心线程池,当非核心任务线程池出问题时,不影响核心线程的处理。

2.进程隔离的典型例子就是单体系统拆分成多个系统。随着系统的发展变化,系统所包含的模块和功能会越来越多,极有可能其中一个模块出问题影响到其他模块。通过将系统拆分成多个子系统的进程隔离方式可以有效解决这种问题。

3.集群(分组)隔离主要是通过将服务分级分组独立部署的方式来隔离故障。举个例子,系统中商品服务会提供给多个下游调用,其中有核心的交易业务,也有其他非核心的业务,为了保证其他非核心的服务出故障时不影响核心交易,可以对商品服务做分级部署,核心集群和非核心集群的SLA甚至服务器资源可以不一致,这样既保证了故障的隔离性,也充分利用了服务器资源。

4.机房隔离包含两个层次的含义:一方面是系统为了满足高可用性的需求,需要多机房进行部署,当一个机房出现不可控的故障时可以通过流量迁移的方式引流到其他正常的机房;第二个方面是机房内尽量保持封闭隔离,也就是说尽量保证服务本机房优先调用,这样可以避免在机房间网络出问题或者其他机房故障时不受影响。

【最佳实践】

1.设计系统时要全面考虑好是否需要隔离性,如果是服务多个核心与非核心业务,最好通过服务分机的方式拆分部署,对不同的集群承诺不同的SLA。

2.隔离需要系统化的思考和设计,从线程隔离、进程隔离、集群隔离、机房隔离几个层次逐层递进。

【安全生产指南八-同步异步】

同步与异步并没有孰优孰劣,在系统设计中选用同步或异步实现必须带入实际场景。但是站在稳定性的视角,同步交互会比异步交互带来更高的故障率,原因也很简单,同步的反馈是即时的,而异步会有一定的时间弹性,利用好异步的时间弹性则可以为我们规避很多不必要的故障。试想在一个同步调用链条中,如果有其中的一个系统响应变慢或者出现故障,整个调用链的吞吐量就会急剧下降。

同步调用的优势在于简单直接,工程师在编写代码和调试时非常方便。因此在实际的项目设计编码中,可能会更倾向于用同步调用来实现需求,长此以往,随着业务流程的变化累积调用链路可能会越来越长也越复杂,而整条链路的可用性则是链路上各个系统可用性的乘积。举个例子,系统链路A->B->C->D,其中ABCD可用性均为99.9%,则整条链路的可用性最终为P(A)P(B)P(C)P(D)=99.9%99.9%99.9%99.9%=96.05%.因此在设计系统的时候,能异步处理的流程尽量采用异步,一方面可以解耦弱依赖,另外一方面可以通过异步的特性来给故障恢复更多的缓冲空间

【最佳实践】

1.在做系统设计的时候,涉及系统间交互或系统内流程模块交互,能采用异步通信的话尽量采用异步。

2.一些常见的场景,如相互独立的任务、长耗时任务等都可以采用异步,减少阻塞、降低串联失败的可能性.

【安全生产指南九-设计篇】

设计是把一种设想通过合理的规划,周密的计划,通过各种感觉形式传达出来的过程。设计是将目标更好变现的过程。回到软件设计上来,就体现在如何将软件高度抽象,解耦以达到分而治之的过程。

设计是如此重要,我们既要具备对事物的抽象,解耦能力,又要能够从细节上作把控,做到大处着眼,小处着手。对于方法论,软件设计领域也诞生了很多软件设计思想,比如面向过程设计,面向对象设计,面向服务设计,面向消息设计,面向失败设计等,每种思想也都是在企业软件发展不同阶段解决某个领域或某一类的问题,没有好与坏的区别。今天,随着阿里巴巴经济体的战略发展布局已经深入到各个领域影响到人民生活的方方面面,任何一点点的故障都可能带来严重的后果,因此面向失败设计显得尤为重要。我们需要横向从网络,dns,cdn,软负载,中间件,容器,存储,数据库等维度去梳理沉淀经验,也需要从纵向运维发布,监控报警,管控平台,调度,环境部署等维度梳理。 以下常用的参考指标:

编码设计模块,服务,字段等设计的时候,需要考虑命名的可读性,见名知意,避免产生歧义。 接口设计需要满足开闭原则。

分布式设计需要考虑一致性,避免脑裂问题产生。

缓存设计确定命中率指标的前提下,需要持续观察未命中数据特征,特别是无效的查询,容易穿透缓存,命中数据库。

容量设计自身稳态及尖刺容量评估确定的前提下,做好容量保护相应措施,比如限流,降级,隔离等

依赖设计做好强弱依赖梳理,避免核心功能依赖非核心系统,非核心流程节点,能走异步最好走异步。

日志设计系统日志尽可能异步化,尽量避免无效日志,控制台日志输出

监控设计关键监控项及SLA的指标必须要做监控,监控项尽可能覆盖全,同时要做到有效报警,不要让大量无效报警淹没有价值的报警信息。

权限设计本着够用原则,避免出现大权限,大账号,如果避免不了,需要做天花板限制。

表结构设计分库分表需要考虑热点数据问题,时刻关注表的数据量大小

你可能感兴趣的:(稳定性工程)