系统稳定性和系统可用性是对在线系统很重要的两个评价指标,也是最重要的系统能力,系统可用性或者成熟度不足,将会造成重大的事故或者经济损失。
系统故障在研发团队一般的生命周期如下:
原则按照事前事中事后来分析的话,如下:
- 事前:进行故障预案设立,进行主动防御,降低故障发生概率
- 事中:及时感知故障,并快速定义和定位故障
- 事中:可以快速响应,及时止损
- 事后:故障快速处理,快速恢复
- 事后:故障复盘,吸取教训,制定规范
稳定性保障体系如下:
为开发一套稳定性的应用系统,需要遵循一些设计原则,也有一些手段可以作为抓手。
比如系统简单更好理解,结构也更为清晰,可以做一些扩展性的设计,遵循KISS原则。现实中常见的一些问题是过渡设计,过于炫技,制约了系统的快速迭代能力和快速扩展能力,好的架构师是懂得在多角度做取舍,而不是只有技术的一个角度。
前面文章讲过,将大一体系统拆分为多组件的微服务之后,可以清晰的看到系统边界,更好的面向领域进行设计,也降低了系统复杂度,模块自身也可以更好的自治,符合了软件设计思想的单一职能的原则,但这里也存在拆的过粗或者过细的风险,这种职能依照架构师的天分而来了,粗细都各有理由。但是我个人还是推崇DDD的限界上下文方式进行拆分的,在结合业务复杂度和团队规模进行判断。
做好系统隔离,可以有效防止风险的扩张和传递,之前的文章中介绍了系统隔离和机房隔离。所以可以发现隔离在不同层次上都可以实施,比如系统级别的,数据库级别的,连接池级别的,线程池级别的。隔离原则遵循,主要,次要,核心,非核心等原则就好。
为了避免单点,就需要做好冗余,和多副本。这样也带来了资源和成本问题。之后的资源利用率也是个问题。冗余可以体现在无状态服务层面上,硬件层面上,机房层面上,这些都不能单点部署。所以冗余是高可用很重要的手段。
服务需要做到无状态,有状态会造成什么问题呢?数据一致性,并发控制,数据可靠,服务可靠,幂等性,重试,分布式锁都是有状态服务可能面对到的问题,所以做好无状态服务,你后期的系统技术债会小很多。
异步调用是系统提升性能的很有效手段,大部分场景都可以考虑异步处理,之前在我们周会上还进行过激烈的讨论,大致意思是系统设计或者业务设计上究竟有没有强一致性场景,如果没有是否全部可以做到异步呢?异步处理可以带来性能和弹性两方面的收益。
系统架构的迭代方式根源有很多种,比如业务驱动,技术驱动,甚至有BUG驱动。
我认为一个好的架构师应该是具有悲观主义思想的,时刻想着系统面向失败和故障是如何反应。
他们的思想一般是被莫非定律缠绕着。不心存侥幸是他们的做事法则。
悲观主义架构师需要针对以上所有环节想好备案,想好兜底措施。
但是优秀的架构师应该是乐观主义的,会在研发流程,系统迭代多个角度建立各种独立的特种部队,多个模块系统形成合力,实现1 1大于2的效果。
任何服务因为系统架构问题或是资源成本问题,总会遇到需要加机器扛的情况,而容量规划的方案一般用于这个阶段。
容量规划主要从成本和稳定性平衡之间做取舍。具体投入多少资源,投入到哪里这些不是拍脑袋决定的。我们需要知道系统的水位线在哪里,推算出合力的阈值,可以刚刚好做到限流,降级等预案措施即可。
第一阶段主要靠经验值,理论值来进行预估,也就是拍脑袋阶段。
一般依赖于用户数,单机并发数,连接数,QPS等指标进行拍脑袋。
第二阶段辅助于压测手段进行,对于单个接口,单个节点进行压测,观察机器性能指标,了解性能状况,定位性能瓶颈。
第三阶段通过线上单机压测,这一阶段很重要的一点是采用真实流量进行压测,可以有效还原在线流量及场景。一般手段是线上引流,流量复制,流量回放等手段。线上引流手段通过接入层或者注册中心调整负载权重或者比例,实现机器的不同压力。
第四阶段主要做全链路压测,可以完美还原交易链路的全部系统在压力之下的表现。
上图是来源于阿里,在全链路压测上,阿里走在业界前列,核心步骤如下:
- 链路梳理
- 数据准备和数据脱敏
- 中间件改造,压测标记透传,存储服务建立影子表
- 建立压测模型,流量模型,流量引擎
- 压测预案检查
- 告警监控
- 数据清洗处理
链路中的流量一般呈漏斗模型:
可以发现真实业务场景中,每层服务的真实流量不一样,负载也不一样。
我们能做的就是接近真实流量,力图还原真实现场。
系统总有一个安全水位值,一般参考值如下:
- 水位标准:单机房部署水位在70%以下,双机房水位控制在40%以下
- 单机水位:单机负载 / 单机容量
- 集群水位:集群负载 / 集群容量
- 理论机器数:实际机器数 * (集群水位 / 水位标准)
在线服务总是需要做好预案体系的,还是那句话:不能报侥幸心理。
原则如下:
- 事前制定和完善预案
- 日常演练预案
- 事中统一指挥,收集数据,决策并执行
- 事后总结并持续完善改进预案
养兵千日用兵一时,预案制定之后,究竟好不好,还是需要在线上跑一下的。不然怎么确保关键时刻没问题呢。
阿里内部会是不是做一次演练,还有各种红蓝对抗,混沌工程。
典型的做法是采用故障注入方式验证系统的高可用能力。
故障演练的目的在于:
- 预案是否有效,是否完整
- 监控告警是否准确,是否实时
- 容灾能力,容灾等级是否满足
- 故障是否可复现
- 检查on call机制,验证突发情况团队的战斗力
- 等
混沌工程是一种故障演练和系统高可用的一个实践,最早由奈飞公司提出。就是一个团队不断给系统找麻烦,拔网线,做OOM,打满宽带而验证系统的高可用性和容错能力。
经历了故障演练之后,系统的可用性等级和成熟度就可以知道了。