作者 | 雍雍
来源 | 阿里技术公众号
一 前言
年年有大促,大家对于大促稳定性保障这个词都不陌生,业务场景尽管各不相同,“套路”往往殊路同归,全链路压测、容量评估、限流、紧急预案等,来来去去总少不了那么几板斧。
跳出这些“套路”,回到问题的本质,我们为什么要按照这些策略来做?
除了口口相传的历史经验,我们还能做些什么?又有什么理论依据?
二 怎样的系统算是稳定?
首先回答另一个问题,怎样的系统算是稳定的?
Google SRE中(SRE三部曲[1])有一个层级模型来描述系统可靠性基础和高层次需求(Dickerson's Hierarchy of Service Reliability),如下图:
该模型由Google SRE工程师Mikey Dickerson在2013年提出,将系统稳定性需求按照基础程度进行了不同层次的体系化区分,形成稳定性标准金字塔模型。
金字塔的底座是监控(Monitoring),这是一个系统对于稳定性最基础的要求,缺少监控的系统,如同蒙上眼睛狂奔的野马,无从谈及可控性,更遑论稳定性。更上层是应急响应(Incident Response),从一个问题被监控发现到最终解决,这期间的耗时直接取决于应急响应机制的成熟度。合理的应急策略能保证当故障发生时,所有问题能得到有序且妥善的处理,而不是慌乱成一锅粥。事后总结以及根因分析(Postmortem&Root Caue Analysis),即我们平时谈到的“复盘”,虽然很多人都不太喜欢这项活动,但是不得不承认这是避免我们下次犯同样错误的最有效手段,只有当摸清故障的根因以及对应的缺陷,我们才能对症下药,合理进行规避。
假设一个系统从初次发布后就不再进行更新迭代,做好上述三个方面的工作就能基本满足系统对于稳定性的全部需求。可惜目前基本不会存在这样的系统,大大小小的应用都离不开不断的变更与发布,因此要保证系统在这些迭代中持续稳定,测试和发布管控(Testing&Release procedures)是必不可少的。有效的测试与发布策略能保障系统所有新增变量都处于可控稳定区间内,从而达到整体服务终态稳定。除了代码逻辑更新,迭代同样可能带来业务规模及流量的变化,容量规划(Capacity Planning)则是针对于这方面变化进行的保障策略。现有系统体量是否足够支撑新的流量需求,整体链路上是否存在不对等的薄弱节点,都是容量规划需要考虑的问题。
位于金字塔模型最顶端的是产品设计(Product)与软件研发(Development),即通过优秀的产品设计与软件设计使系统具备更高的可靠性,构建高可用产品架构体系,从而提升用户体验。
三 大促稳定性保障方法
从金字塔模型我们可以看到构建维护一个高可用服务所需要做到的几方面工作,那么问题回到大促稳定性,如何体系化地保障大促期间系统稳定性?
大促保障实际上针对于特定业务场景的集中稳定性建设工作,相较于日常保障工作,具有高并发流量、短保障周期的特点,对系统性能与保障时间有明确要求(一般为2个月左右)。
考虑到上述特性,我们如何在短时间内针对大促大流量业务场景对系统稳定性需求进行优化巩固?
既然时间有限,盲目撒网必然不是最佳策略,需要有针对性地从关键点、薄弱点下手。因此第一步,需要获得全局系统链路现状,包括关键外部依赖、重点业务影响等,找到整体保障的核心关注点。接下来进一步分析大促业务数据,得到除系统本身以外的变量干扰因素。以这两者为基础,集中围绕金字塔模型中系统监控、规划容量、应急响应、测试和复盘等几个方面需求对系统进行针对性集中保障建设,得到最终保障结果。
至此,基本获得了完整的大促稳定性保障策略方向,按照执行顺序依次是:
- 系统链路&业务策略梳理(System & Biz Profiling)
- 监控(Monitoring)
- 容量规划(Capacity Planning)
- 应急响应(Incident Response)
- 测试
- 事后总结(Testing & Postmortem)
1 System & Biz Profiling - 系统链路梳理
系统链路梳理是所有保障工作的基础,如同对整体应用系统进行一次全面体检,从流量入口开始,按照链路轨迹,逐级分层节点,得到系统全局画像与核心保障点。
入口梳理盘点
一个系统往往存在十几个甚至更多流量入口,包含HTTP、RPC、消息等都多种来源。如果无法覆盖所有所有链路,可以从以下三类入口开始进行梳理:
核心重保流量入口
- 用户承诺服务SLI较高,对数据准确性、服务响应时间、可靠度具有明确要求。
- 面向企业级用户
资损事件对应入口
- 关联到公司资金收入或者客户资金收入
- 收费服务
大流量入口
- 系统TPS&QPS TOP5~10
- 该类入口虽然不涉及较高SLI与资损要求,但是流量较高,对整体系统负载有较大影响。
节点分层判断
流量入口就如同线团中的线头,挑出线头后就可按照流量轨迹对链路上的节点(HSF\DB\Tair\HBase等一切外部依赖)按照依赖程度、可用性、可靠性进行初级分层区分。
(1)强弱依赖节点判断
- 若节点不可用,链路业务逻辑被中断 or 高级别有损(存在一定耐受阈值),则为业务强依赖;反之为弱依赖。
- 若节点不可用,链路执行逻辑被中断(return error),则为系统强依赖;反之为弱依赖。
若节点不可用,系统性能受影响,则为系统强依赖;反之为弱依赖。
- 按照快速失败设计逻辑,该类节点不应存在,但是在不变更应用代码前提下,如果出现该类节点,应作为强依赖看待。
- 若节点无感可降级 or 存在业务轻微损伤替换方案,则为弱依赖。
(2)低可用依赖节点判断
- 节点服务日常超时严重
- 节点对应系统资源不足
(3)高风险节点判断
- 上次大促后,节点存在大版本系统改造
- 新上线未经历过大促的节点
- 节点对应系统是否曾经出现高级别故障
- 节点故障后存在资损风险
应产出数据
完成该项梳理工作后,我们应该产出以下数据:对应业务域所有核心链路分析,技术&业务强依赖、核心上游、下游系统、资损风险应明确标注。
下图为单条链路分析示例:
2 System & Biz Profiling - 业务策略同步
不同于高可用系统建设体系,大促稳定性保障体系与面向特定业务活动的针对性保障建设,因此,业务策略与数据是我们进行保障前不可或缺的数据。
一般大促业务数据可分为两类,全局业务形态评估以及应急策略&玩法。
全局评估
该类数据从可以帮助我们进行精准流量评估、峰值预测、大促人力排班等等,一般包含下面几类:
- 大促业务时长(XX日-XX日)
- 业务量预估体量(日常X倍)
- 预估峰值日期
- 业务场景预估流量分配
应急策略
该类数据指相较于往年大促活动,本次大促业务变量,可用于应急响应预案与高风险节点评估等,一般包含下面两类:
- 特殊业务玩法
- 应急情况打法策略
3 Monitoring - 监控&告警梳理
目前业界常用的监控手段一般有两种模式,黑盒监控(Black-box monitoring)与白盒监控(White-box monitoring)。黑盒监控面向对象,一般监控正在发生(而非即将发生)的异常,即系统现有故障。而白盒监控主要依赖系统内部指标监控,面向对象的同时也面向原因,可对系统即将面临的异常进行提前预警,也可在异常发生时同步监控下层内部指标,从而定位根本原因。因此大促稳定性保障中,我们一般选择的是白盒监控。
站在监控的角度看,我们的系统从上到下一般可以分为三层:业务(Biz)、应用(Application)、系统(System)。系统层为最下层基础,表示操作系统相关状态;应用层为JVM层,涵盖主应用进程与中间件运行状态;业务层为最上层,为业务视角下服务对外运行状态。
因此进行大促稳定性监控梳理时,可以先脱离现有监控,先从核心、资损链路开始,按照业务、应用(中间件、JVM、DB)、系统三个层次梳理需要哪些监控,再从根据这些索引找到对应的监控告警,如果不存在,则相应补上;如果存在则检查阈值、时间、告警人是否合理。
监控
监控系统一般有四项黄金指标:延时(Latency), 错误(Error),流量(Traffic), 饱和度(Situation),各层的关键性监控同样也可以按照这四项指标来进行归类,具体如下:
表 1
告警
是不是每项监控都需要告警?答案当然是否定的。建议优先设置Biz层告警,因为Biz层我们对外服务最直观业务表现,最贴切用户感受。Application&System层指标主要用于监控,部分关键&高风险指标可设置告警,用于问题排查定位以及故障提前发现。
对于一项告警,我们一般需要关注级别、阈值、通知人等几个点。
1)级别
即当前告警被触发时,问题的严重程度,一般来说有几个衡量点:
- 是否关联GOC
- 是否产生严重业务影响
- 是否产生资损
2)阈值
即一项告警的触发条件&时间,需根据具体场景合理制定。一般遵循以下原则:
- 不可过于迟钝。一个合理的监控体系中,任何异常发生后都应触发相关告警。
- 不可过于敏感。过于敏感的阈值会造成频繁告警,从而导致响应人员疲劳应对,无法筛选真实异常。若一个告警频繁出现,一般是两个原因:系统设计不合理 or 阈值设置不合理。
- 若单一指标无法反馈覆盖整体业务场景,可结合多项指标关联构建。
- 需符合业务波动曲线,不同时段可设置不同条件&通知策略。
3)通知人&方式
若为业务指标异常(Biz层告警),通知人应为问题处理人员(开发、运维同学)与业务关注人员(TL、业务同学)的集合,通知方式较为实时,比如电话通知。
若为应用 & 系统层告警,主要用于定位异常原因,通知人设置问题排查处理人员即可,通知方式可考虑钉钉、短信等低干扰方式。
除了关联层次,对于不同级别的告警,通知人范围也可适当扩大,尤其是关联GOC故障的告警指标,应适当放宽范围,通知方式也应更为实时直接。
应产出数据
完成该项梳理工作后,我们应该产出以下数据:
系统监控模型,格式同表1
- Biz、Application、System 分别存在哪些待监控点
- 监控点是否已全部存在指标,仍有哪些待补充
系统告警模型列表,需包含以下数据
- 关联监控指标(链接)
- 告警关键级别
- 是否推送GOC
- 是否产生资损
- 是否关联故障
- 是否关联预案
- 业务指标大盘,包含Biz层重点监控指标数据。
- 系统&应用指标大盘,包含核心系统关键系统指标,可用于白盒监控定位问题。
4 Capacity Planning - 容量规划
容量规划的本质是追求计算风险最小化和计算成本最小化之间的平衡,只追求任意其一都不是合理的。为了达到这两者的最佳平衡点,需尽量精准计算系统峰值负载流量,再将流量根据单点资源负载上限换算成相应容量,得到最终容量规划模型。
流量模型评估
1)入口流量
对于一次大促,系统峰值入口流量一般由常规业务流量与非常规增量(比如容灾预案&业务营销策略变化带来的流量模型配比变化)叠加拟合而成。
(a)常规业务流量一般有两类计算方式:
历史流量算法:该类算法假设当年大促增幅完全符合历史流量模型,根据当前&历年日常流量,计算整体业务体量同比增量模型;然后根据历年大促-日常对比,计算预估流量环比增量模型;最后二者拟合得到最终评估数据。
由于计算时无需依赖任何业务信息输入,该类算法可用于保障工作初期业务尚未给出业务总量评估时使用,得到初估业务流量。
业务量-流量转化算法(GMV\DAU\订单量):该类算法一般以业务预估总量(GMV\DAU\订单量)为输入,根据历史大促&日常业务量-流量转化模型(比如经典漏洞模型)换算得到对应子域业务体量评估。
该种方式强依赖业务总量预估,可在保障工作中后期使用,在初估业务流量基础上纳入业务评估因素考虑。
(b)非常规增量一般指前台业务营销策略变更或系统应急预案执行后流量模型变化造成的增量流量。例如,NA61机房故障时,流量100%切换到NA62后,带来的增量变化。
考虑到成本最小化,非常规增量P计算时一般无需与常规业务流量W一起,全量纳入叠加入口流量K,一般会将非常规策略发生概率λ作为权重,即:
2)节点流量
节点流量由入口流量根据流量分支模型,按比例转化而来。分支流量模型以系统链路为计算基础,遵循以下原则:
- 同一入口,不同链路占比流量独立计算。
- 针对同一链路上同一节点,若存在多次调用,需计算按倍数同比放大(比如DB\Tair等)。
- DB写流量重点关注,可能出现热点造成DB HANG死。
容量转化
1)Little Law衍生法则
不同类型资源节点(应用容器、Tair、DB、HBASE等)流量-容量转化比各不相同,但都服从Little Law衍生法则,即:
2)N + X 冗余原则
- 在满足目标流量所需要的最小容量基础上,冗余保留X单位冗余能力
- X与目标成本与资源节点故障概率成正相关,不可用概率越高,X越高
- 对于一般应用容器集群,可考虑X = 0.2N
上述法则只能用于容量初估(大促压测前&新依赖),最终精准系统容量还是需要结合系统周期性压力测试得出。
应产出数据
- 基于模型评估的入口流量模型 & 集群自身容量转化结果(若为非入口应用,则为限流点梳理)。
- 基于链路梳理的分支流量模型 & 外部依赖容量转化结果。
5 Incident Response - 紧急&前置预案梳理
要想在大促高并发流量场景下快速对线上紧急事故进行响应处理,仅仅依赖值班同学临场发挥是远远不够的。争分夺秒的情况下,无法给处理人员留有充足的策略思考空间,而错误的处理决策,往往会导致更为失控严重的业务&系统影响。因此,要想在大促现场快速而正确的响应问题,值班同学需要做的是选择题(Which),而不是陈述题(What)。而选项的构成,便是我们的业务&系统预案。
从执行时机与解决问题属性来划分,预案可分为技术应急预案、技术前置预案、业务应急预案、业务前置预案等四大类。结合之前的链路梳理和业务评估结果,我们可以快速分析出链路中需要的预案,遵循以下原则:
- 技术应急预案:该类预案用于处理系统链路中,某层次节点不可用的情况,例如技术/业务强依赖、弱稳定性、高风险等节点不可用等异常场景。
- 技术前置预案:该类预案用于平衡整体系统风险与单节点服务可用性,通过熔断等策略保障全局服务可靠。例如弱稳定性&弱依赖服务提前降级、与峰值流量时间冲突的离线任务提前暂定等。
- 业务应急预案:该类预案用于应对业务变更等非系统性异常带来的需应急处理问题,例如业务数据错误(数据正确性敏感节点)、务策略调整(配合业务应急策略)等
- 业务前置预案:该类预案用于配和业务全局策略进行的前置服务调整(非系统性需求)
应产出数据
完成该项梳理工作后,我们应该产出以下数据:
- 执行&关闭时间(前置预案)
- 触发阈值(紧急预案,须关联相关告警)
- 关联影响(系统&业务)
- 决策&执行&验证人员
- 开启验证方式
- 关闭阈值(紧急预案)
- 关闭验证方式
阶段性产出-全链路作战地图
进行完上述几项保障工作,我们基本可得到全局链路作战地图,包含链路分支流量模型、强弱依赖节点、资损评估、对应预案&处理策略等信息。大促期间可凭借该地图快速从全局视角查看应急事件相关影响,同时也可根据地图反向评估预案、容量等梳理是否完善合理。
6 Incident Response - 作战手册梳理
作战手册是整个大促保障的行动依据,贯穿于整个大促生命周期,可从事前、事中、事后三个阶段展开考虑。
整体梳理应本着精准化、精细化的原则,理想状态下,即便是对业务、系统不熟悉的轮班同学,凭借手册也能快速响应处理线上问题。
事前
1)前置检查事项清单
大促前必须执行事项checklist,通常包含以下事项:
- 集群机器重启 or 手动FGC
- 影子表数据清理
- 检查上下游机器权限
- 检查限流值
- 检查机器开关一致性
- 检查数据库配置
- 检查中间件容量、配置(DB\缓存\NoSQL等)
- 检查监控有效性(业务大盘、技术大盘、核心告警)
- 每个事项都需包含具体执行人、检查方案、检查结果三列数据
2)前置预案
域内所有业务&技术前置预案。
事中
1)紧急技术&业务预案
需要包含的内容基本同前置预案,差异点如下:
- 执行条件&恢复条件:具体触发阈值,对应监控告警项。
- 通知决策人。
2)应急工具&脚本
常见故障排查方式、核心告警止血方式(强弱依赖不可用等),业务相关日志捞取脚本等。
3)告警&大盘
应包含业务、系统集群及中间件告警监控梳理结果,核心业务以及系统大盘,对应日志数据源明细等数据:
- 日志数据源明细:数据源名称、文件位置、样例、切分格式。
- 业务、系统集群及中间件告警监控梳理结果:关联监控指标(链接)、告警关键级别、是否推送GOC、是否产生资损、是否关联故障、是否关联预案。
- 核心业务&系统大盘:大盘地址、包含指标明细(含义、是否关联告警、对应日志)。
4)上下游机器分组
应包含核心系统、上下游系统,在不同机房、单元集群分组、应用名,可用于事前-机器权限检查、事中-应急问题排查黑屏处理。
5)值班注意事项
包含每班轮班同学值班必做事项、应急变更流程、核心大盘链接等。
6)核心播报指标
包含核心系统&服务指标(CPU\LOAD\RT)、业务关注指标等,每项指标应明确具体监控地址、采集方式。
7)域内&关联域人员通讯录、值班
包含域内技术、TL、业务方对应排班情况、联系方式(电话),相关上下游、基础组件(DB、中间件等)对应值班情况。
8)值班问题记录
作战记录,记录工单、业务问题、预案(前置\紧急)(至少包含:时间、问题描述(截图)、影响分析、决策&解决过程等)。值班同学在值班结束前,进行记录。
事后
1)系统恢复设置事项清单(限流、缩容)
一般与事前检查事项清单对应,包含限流阈值调整、集群缩容等大促后恢复操作。
2)大促问题复盘记录
应包含大促遇到的核心事件总结梳理。
7 Incident Response - 沙盘推演
实战沙盘演练是应急响应方面的最后一项保障工作,以历史真实故障CASE作为应急场景输入,模拟大促期间紧急状况,旨在考验值班同学们对应急问题处理的响应情况。
一般来说,一个线上问题从发现到解决,中间需要经历定位&排查&诊断&修复等过程,总体遵循以下几点原则:
- 尽最大可能让系统先恢复服务,同时为根源调查保护现场(机器、日志、水位记录)。
- 避免盲目搜索,依据白盒监控针对性诊断定位。
- 有序分工,各司其职,避免一窝蜂失控乱象。
- 依据现场情况实时评估影响范围,实在无法通过技术手段挽救的情况(例如强依赖不可用),转化为业务问题思考(影响范围、程度、是否有资损、如何协同业务方)。
- 沙盘演练旨在检验值班同学故障处理能力,着重关注止血策略、分工安排、问题定位等三个方面:
国际化中台双11买家域演练
根据故障类型,常见止血策略有以下解决思路:
入口限流:调低对应Provider服务来源限流值
- 应对突发流量过高导致自身系统、下游强依赖负载被打满。
下游降级:降级对应下游服务
- 下游弱依赖不可用。
- 下游业务强依赖经业务同意后降级(业务部分有损)。
单点失败移除:摘除不可用节点
- 单机水位飙高时,先下线不可用单机服务(无需下线机器,保留现场)。
- 应对集群单点不可用、性能差。
切换:单元切流或者切换备份
- 应对单库或某单元依赖因为自身原因(宿主机或网络),造成局部流量成功率下跌下跌。
Google SRE中,对于紧急事故管理有以下几点要素:
- 嵌套式职责分离,即分确的职能分工安排
- 控制中心\作战室
- 实时事故状态文档
- 明确公开的职责交接
其中嵌套式职责分离,即分确的职能分工安排,达到各司其职,有序处理的效果,一般可分为下列几个角色:
- 事故总控:负责协调分工以及未分配事务兜底工作,掌握全局概要信息,一般为PM/TL担任。
- 事务处理团队:事故真正处理人员,可根据具体业务场景&系统特性分为多个小团队。团队内部存在域内负责人,与事故总控人员进行沟通。
- 发言人:事故对外联络人员,负责对事故处理内部成员以及外部关注人员信息做周期性信息同步,同时需要实时维护更新事故文档。
- 规划负责人:负责外部持续性支持工作,比如当大型故障出现,多轮排班轮转时,负责组织职责交接记录。
相关阅读
[1] https://landing.google.com/sre/books/
https://sre.google/sre-book/table-of-contents/
https://sre.google/workbook/table-of-contents/