大拿的思考,记录学习一下
1. 目的及执行方法
通过本文,期望能够梳理清楚当前系统对于常规风险分类的应对能力,并对每一个问题,给出后续三种方案中的一种:
- 通过运维调整部署方案来解决该问题;
- 通过研发调整架构或系统实现的容错性来彻底根治该问题;如果无法短时间内解决,可以通过work around的方法临时解决,但必须标记其状态及后续计划,定期Review;较多的work around的存在,是系统风险的典型标识;
- 无法通过上述两种方案解决的,运维制定对应的预案,手动或自动触发执行;
输出形式
- 对于所有系统,输出其风险点列表;
- 风险点的模板如附件表格;
该列表通过如下方式不断进行调整:
- 定期或根据本指导方法进行Review;
- 在系统大的架构调整或升级时,进行Review;
- 在每次事故或报障的Case Study后进行
在对每个系统进行梳理时,需要落实到每个模块;
该过程的多个环节,都需要跟监控密切相关,依赖于监控的完善度;都需要回答如下问题:
- 是否能够监控到异常;
- 是否有预案可以执行;预案的ID是什么?
- 是否能够自动执行;
2. 故障点
2.1 典型情况
对于每个系统的每个模块都需要包括如下:
- 一台机器的故障:
- 背景:机器一定会出现故障;
- 原则:一台机器的任何故障,都不应该带来业务影响;也不需要立即处理;
- 问题:
- 一台机器完全故障(死机、断网等)是否会对服务产生影响?
- 一台机器部分故障(硬盘写满、硬盘IO错误或者慢、内存、CPU使用率高等)是否会对该服务产生影响?
- 一个机架的故障:
- 背景:机架可能出现各种故障(如整机架掉电、网络中断、网络闪断等);
- 原则:
- 一个机架的故障不应该给系统带来影响,至少不应该是严重影响;
- 同一个模块的多个实例应该打散在多机架,并对分布进行Review;除由于设计原因产生的特殊需求外;
- 场景与问题:
- 对于当前的部署情况,一个机架故障,是否会对服务产生影响?
- 当前的服务部署情况,是否满足机架打散的原则?
- 该服务对机架分布是否存在特殊要求?
- 单实例的故障:
- 背景:服务的实例,会因为各种原因(如机器故障、异常退出或hang住、部署退出等)而停止或不正常工作;
- 原则:
- 任意服务应该有实例异常的阈值,低于阈值个数的实例的任何故障,都不应该带来业务影响;也不需要立即处理;
- 关于单点:对于读服务,不允许出现单点;写服务,必须有热备或冷备的方案;
- 单实例故障可以在调度层自动容错,服务不能因为单实例故障而出现损失;
- 问题:
- 是否有有效的方法,来判断实例不能正常工作?
- 实例不正常工作的判断方法,是否会引起全局误判的可能性?是否有保底方案?
- 实例不正常工作后,是否能及时实现实现负载的转移?(方案是什么,多久会生效?)
- 系统是否存在单点?
- 单点是否有备份方案?(方案是什么?)
- 机房的故障:
- 背景:机房会因为网络、电力、空调等因素发生整体中断;
- 原则:
- 对于核心服务,应该能够处理单机房故障;
- 问题:
- 是否做到跨机房冗余?
- 是否有有效的监控能够判定单机房故障?
- 是否能及时对机房故障做到切换或自动容错?(多久?方案是什么?)
- 逻辑分组及逻辑分组的故障:
- 背景:逻辑分组是上线、物理部署、流量调度的基本单位,是可用性保障的基础;逻辑分组可以独立运行,承载所有业务;
- 原则:
- 所有服务必须有逻辑分组;逻辑分组的拆分依据业务的不同而不同,典型的有按照地域、按照机房、按照流量成分来进行;
- 单个逻辑分组的异常,不能影响整体服务;
- 问题:
- 当前服务是否有独立逻辑分组的划分?(划分维度是什么?)
- 单个逻辑分组异常是否会对业务产生影响?
- 是否有有效的方法来判断逻辑分组异常?
- 逻辑分组的异常,是否能够快速切换?(切换方案和时效性分别是什么?)
- 依赖故障
- 背景:任何所依赖的服务,都存在发生各种故障的可能性;
- 原则:
- 所有的依赖,不应该写死IP、证书等;
- 能够容错下游的单实例故障;
- 能够在机房级故障上与下游做好协调(要么能容错,要么从源头迁移);
- 做好必要的降级;
- 对第三方组件,要有掌控能力;
- 问题:写出所有依赖(包括第三方库跟组件),对每个依赖回答如下问题
- 如果该依赖发生不可用(包括缓慢),当前模块是否能够正常工作?
- 是否能容忍该依赖的实例级故障?(能容忍多少比例的实例故障,通过什么方法实现的,时效性是什么,是否存在全局误判的可能性)
- 是否能够容忍该依赖的机房级故障?(方案是什么?)
- 对于该依赖,是否知晓其容量限制和SLA?
- 对于该依赖,是否有写死的IP、证书等?
- 对于该依赖,公司内是否存在对其完全掌控的负责方?
- 对于使用数据库的情况,是否存在慢查询问题?慢查询是否会导致连接池整体耗尽?
2.2 流量与容量
- 容量:
- 背景:外部流量会存在不可控的情况,系统需要能够应对,保证其处理能力,不至于发生全局崩溃;
- 原则:
- 容量数据:每个调度入口,必须具备明确的容量数据,并定期更新;容量数据需要考虑到不同功能的Cost不同;
- 保护机制:超过容量的情况下,系统应该有保护机制提供稳定输出,不允许发生崩溃;
- 防攻击:除网络层的防护外,业务层必须具备对攻击流量的防护能力,发现和规避常见的共计行为;
- 隔离与限流:至少在源头处,具备基于IP、用户、子系统等不同维度的限流与防护能力,避免系统被单一的来源请求耗尽;
- 严谨Review系统的每层超时和重试机制,考虑极端情况下,不引起系统整体的崩溃;
- 问题:
- 对于每个模块和系统,是否存在经过测试和验证的容量数据?
- 超过容量数据后,系统是否有对应的机制能够保证额定内的请求不受影响?(机制是什么?)
- 是否有能够基于IP、用户、子系统等维度进行隔离和限流?
- 在系统的各级超时及重试均达到最大的情况下,系统是否能承受放大后的流量?
- 是否会存在定时的同步行为?是否对定时同步进行随机化处理?
- 在出现机房级网络抖动的情况下,是否能够应对调用方的重试?
- 流量调度能力:
- 背景:
- 系统应该具备基础的流量调度的能力,来保证在多个逻辑单位之间调度,来保证可用性或实现隔离;
- 原则:
- 流量应该具备明确的标识分类,包括流量分级。这是后续流量调度及资源分配和控制的前提;
- 具备按照内外网、单运营商、单物理机房、流量分类和分级标识的调度能力;
- 问题:
- 是否具备自动确定流量来源的能力?(如何来确定?是否能够应用在调度里面?)
- 是否具备按照流量来源、流量分级、流量功能进行调度的能力?
- 背景:
- 异常检查
- 背景:
- 所有来自于外部的输入,都有可能有意或者无意产生恶意影响,程序要能够正确处理;
- 原则:
- 必须对输入做严格校验,来规避可能的可用性或安全风险;
- 问题:
- 所有的输入,是否都经过校验?
- 所有的数据库相关,是否都做过转义处理?
- 所有命令执行的代码,是否都做过转义处理?
- 是否会有测试流量进入生产系统?
- 背景:
- 功能隔离
- 背景:非核心功能的实现,往往在性能上的考虑较少,在出现较大流量变化时,会对核心功能产生影响;
- 原则:
- 核心功能在处理上要与非核心功能区分开,能够做到非核心功能不影响核心功能,必要时可以牺牲非核心功能;
- 问题:
- 系统是否区分了核心功能和非核心功能?
- 核心功能和非核心功能的部署实现是否在一起?
- 核心功能和非核心功能在资源上是否存在争抢?
- 非核心功能是否可以被降级掉?
2.3 其他
- 启动与热加载:
- 背景:服务的变更生效时间比较慢,会影响止损的速度;
- 原则:
- 服务的启动时间需要快速(不能超过 10 ? 秒);
- 与流量调度相关的配置,需要能够热加载(如负载均衡、调度策略、超时重试等),以提高止损效率;
- 问题:
- 当前服务的启动时间是否小于 10s?
- 流量调度配置能否热加载?
- 数据
- 背景:数据会因为各种各样的原因而丢失,如程序Bug、运维操作、物理故障等。
- 原则:
- 必须有多层次的数据保全方案;
- 问题:
- 数据删除,是否有伪删除的机制?
- 是否有可以快速恢复(10分钟内)的备份方案?
- 是否有独立且与当前系统物理上隔离的数据备份方案?
- 灾难
- 背景:灾难会发生。
- 原则:
- 所有系统必须有额外的兜底方案;
- 问题:
- 对于系统的灾难级异常,是否有快速的兜底方案?
- 是否有从0恢复的能力?
3. 预案
预案用于解决上述风险无法通过程序自动处理的风险点。对于所有预案,必须:
- 定期梳理和演练,确保预案的有效性;
- 改进或消除预案,考虑从根本上消除预案解决的问题,预案越多,代表系统的实现和容错越差;
一个预案需要包括如下内容:
- 预案编号:系统名称,加系统内的编号;
- 预案名称:简明扼要代表预案要解决的问题;
- 预案故障等级:
- 预案触发条件:必须是严格对应到监控的,哪个监控报警就必须触发这个预案,不应该出现复杂的判定逻辑;
- 预案执行动作:给出预案的具体执行动作或者对应文档的链接;
- 预案演练周期:默认根据预案等级来定,也可以自行指定;
- 演练计划: