研发效能参考课程《研发效率破局之道》,稳定性保障参考《SRE实战手册》。
一、研发效能
1)效能度量
推荐从团队和个人这两个维度对度量指标进行分类,其中团队维度中又分为速度、准确度和质量 3 类,所以一共是 4 类。
- 速度:天下武功,唯快不破,速度指标主要用来衡量团队研发产品的速率。比如,前置时间,从任务产生到交付的时长。
- 准确度:关注产品是否跟计划吻合,跟用户需求吻合,能否提供较大的用户价值。一个例子是功能的采纳率,也就是有百分之多少的用户使用了功能 x。
- 质量:如果质量有问题,产品的商业价值会被大打折扣。质量包括产品的性能、功能、可靠性、安全等方面。
- 个人效能:个人开发过程中的效率指标,比如开发环境生成速度、本地构建速度等。
总结了一张导图,展示了这 4 个方面的度量指标,供参考。可以看到,一共给出了 40 多个指标。
提供用户价值是公司存在的根本,因此与之相关的指标是最重要的。这一点非常好理解。从这个角度来看,以下几个相关度量指标比较有效:
- 净推荐值 (Net Promoter Score,NPS),是通过调研了解用户满意度,实用性很强。
- 系统 /App 宕机时间 (System/App Downtime) 和严重线上事故数 (Incidents),衡量的是系统的可用性,通常与用户价值直接挂钩。
- 热修复上线时间 (Hotfix Time),指的是从编码完成到部署到生产的时长,关系到解决重大缺陷的效率,与用户价值强相关。
在度量效能时,很多团队往往是一上来就不加辨别地扎到某几个竖井里去寻找问题。这样的局部优化往往对全局优化无效,还会影响团队之间的关系,带来负面效果。正确的做法应该是,先检查全局,找到关键瓶颈之后,再进入细节分析和解决的环节。具体实现起来,方法也很简单,就是收集产品周期中每一个阶段所占用的时间,包括计划的时间和最后实际花费的时间,然后寻找问题最大的地方。
针对个人研发效能作评价,可以采用类似 360 度绩效考评的方式来收集同事之间的评价。评价的标准基于在用户价值输出上做出的贡献,包括自身产生的价值,以及帮助团队成员产生的用户价值。下面列了一些可以用来收集反馈的问题,涵盖开发效率、质量、团队贡献等方面。
作为管理者 / 内部效能团队,应该关注开发人员的高频活动,并自动化和优化这些步骤,让开发人员能专注开发。
2)程序员聚焦开发
持续开发(不受阻塞的开发状态)的基本原则主要包括两条:
- 规范化、自动化核心步骤。根据团队实际情况,找到合适的工具和配置进行这些检查,并让团队成员统一使用。
- 快速反馈,增量开发。灵活使用各种 Linter 和测试;建设并优化沙盒环境;使用实时检查工具。
3)高效协同
如何做到信息流通,从而让开发人员更顺畅地生产出高价值的产品。总结来说,就是要从以下三个方面入手:
- 首先,从人入手,建设共享文化,鼓励共享行为,使信息共享与团队成员利益一致,从而让大家愿意共享。
- 然后,在流程和工具方面,针对与研发相关的信息,设计并实现对应代码、文档的共享,以及信息在流水线上的自动化流动。
- 最后,在沟通技巧上下功夫,掌握高效沟通的原则,根据场景选择合适的沟通方式和工具。
4)代码审查
代码审查的作用很多,主要表现在 5 个方面。
- 作用 1,尽早发现 Bug 和设计中存在的问题。
- 作用 2,提高个人工程能力。
- 作用 3,团队知识共享。
- 作用 4,针对某个特定方面提高质量。
- 作用 5,统一编码风格。
按照审查范围,代码审查可以分为增量审查和全量审查两类。
5)技术债
控制技术债主要有以下 4 步:
- 让公司管理层意识到偿还技术债的重要性,从而愿意投入资源。
- 采用低成本的方式去预防。由于开发团队的能力问题引入的技术债,可以使用加强计划和代码审查等方法实现低成本的预防。
- 识别技术债并找到可能的解决方案。对于主动引入的技术债,可以在引入的时候就添加任务到 Backlog。而对于被动引入的技术债,则需要周期性的审视,这需要技术管理者主动地收集、整理技术债问题。
- 持续重构,解决高优先级技术债。作为技术管理者,除了业务目标外,还要制定团队的技术目标,来解决最重要、最紧急的技术债任务。
6)测试左移
向左扩展,就是让测试介入代码提测之前的部分。比如,扩展到开发阶段,在架构设计时就考虑产品的可测试性,并尽量进行开发自测等。另外,测试可以更进一步扩展到需求评审阶段,让测试人员不只是了解需求,更要评估需求的质量,比如分析需求的合理性以及完整性等。
要做好测试左移,有 3 个基本原则:
- 调整团队对测试的态度。
- 把测试添加到开发和产品需求步骤中。
- 频繁测试,快速测试。
7)效率心法
在实践中被证明有效的 3 条原则,包括:
- 抽象和分而治之,这个拆分处理的过程,就是常说的分而治之;而用子系统来隐藏一个领域的内部细节,就是抽象。
- 快速迭代,不要过度计划,尽量让自己的代码能够尽快运行起来。
- DRY(Don’t Repeat Yourself),代码逻辑的重复,不仅仅是工作量的浪费,还会大大降低代码的质量和可维护性。
8)深度工作
实现深度工作的办法可以概括为以下三步:
- 以终为始,寻找并聚焦最重要的任务。
- 追根究底,寻找最高效的解决方案。
- 安排时间和精力,高效执行解决方案。
二、稳定性保障
1)稳定性指标
SRE(Site Reliability Engineering,网站可靠性工程) 是一套体系化的稳定性保障方法,下面是一张 SRE 框架图。从职能分工上,SRE 体系的建设绝不是单个岗位或单个部门就能独立完成的,必然要求有高效的跨团队组织协作才可以。
从业界稳定性通用的衡量标准看,有两个非常关键的指标:
- MTBF(Mean Time Between Failure),平均故障时间间隔。
- MTTR(Mean Time To Repair), 故障平均修复时间。
通俗地说,MTBF 指示了系统正常运行的阶段,而 MTTR 则意味着系统故障状态的阶段。如果想提升稳定性,就会有两个方向:提升 MTBF,也就是减少故障发生次数,增加故障发生间隔时长;降低 MTTR,故障不可避免,那就提升故障处理效率,减少故障影响时长。
MTTR 可以细分为 4 个指标:MTTI、MTTK、MTTF 和 MTTV。
2)可用性指标
目前业界有两种衡量系统可用性的方式,一个是时间维度,一个是请求维度,我们先来看这两个维度的计算公式。
- 时间维度:Availability = Uptime / (Uptime + Downtime)
- 请求维度:Availability = Successful request / Total request
时长维度,是从故障角度出发对系统稳定性进行评估。可以用一系列的标准和判定逻辑来说明系统是否正常。比如,系统请求状态码为非 5xx 的比例,也就是请求成功率低于 95%,已经连续超过 10 分钟,这时就要算作故障,那么 10 分钟就要纳入 Downtime(宕机时间),如果达不到这个标准,就不算作故障,只是算作一般或偶然的异常问题。
这里有三个要素:衡量指标,系统请求状态码;衡量目标,非 5xx 占比,也就是成功率达到 95%;影响时长,持续 10 分钟。
因此,只有当问题达到一定影响程度才会算作故障,这时才会计算不可用时长,也就是上面公式中的 Downtime。同时,还要求一个周期内,允许的 Downtime,或者说是系统的“生病时间”是有限的,用这个有限时间来约束系统稳定性。下面是常见的按时长维度统计的可用性对照表:
这里最显著的问题就是,稳定性只与故障发生挂钩。所以这种用时长维度来衡量系统稳定性的方式,其主要缺点就是粒度不够精细。这些小的异常问题和它们的影响,如果从更长的周期来看,也是有一定参考价值的。这就需要第二种衡量方式了,也就是从请求维度来衡量系统可用性。
用一句话来说,请求维度,是从成功请求占比的角度出发,对系统的稳定性进行评估。假定系统一天内有 10W 次请求,期望的成功率至少是 95%,如果有 5001 次请求失败了,也就是成功率低于 95% 了,就认为系统运行状态是不正常的。
请求维度的系统可用性同样包含三个关键要素,第一个衡量指标,请求成功率;第二个衡量目标,成功率达到 95% 才算系统运行正常;第三个是统计周期,比如一天、一周、一个月等等,在一个统计周期内计算整体状况,而不是看单次的。
到这里,可以总结出一条至关重要的经验:故障一定意味着不稳定,但是不稳定,并不意味着一定有故障发生。
3)On-Call机制
MTTR 细分为 4 个指标:MTTI、MTTK、MTTF 和 MTTV,之所以分组分块,也是为了更加有目的性地做到系统稳定性。
在一个分布式的软件系统下,判定一个问题发生在哪儿,影响范围到底是怎么样的,要召集哪些人共同参与定位排查等等,这个会消耗更多时间,所以 MTTI 阶段占比会更重。
MTTI,就是故障的平均确认时间,也就是从故障实际发生时间点,到触发采取实际行动去定位前的这段时间。这个环节其实主要有两件事情要做:
- 第一件事,判断出现的问题是不是故障。
- 第二件事,确定由谁来响应和召集。
第一件事其实主要依赖于监控和告警体系。这里再强调一下,在 On-Call 阶段,并不是所有的告警都要响应,如果不影响稳定性,一般的告警是可以降低响应级别的。第二件事往往容易被忽视,也就是 On-Call 的流程机制建设。
On-Call 关键 5 步法:
- 确保关键角色在线。这里的关键角色不是指一两个值班的运维或 SRE 人员,而是整个产品体系中的所有关键角色。
- 组织 War Room 应急组织。创建专门处理故障的“消防群”(暗含着灭火的意思),将关键角色纳入其中。
- 建立合理的呼叫方式。建议使用固定的 On-Call 手机,建立手机与所有 On-Call 系统的对应关系,比如这个手机号码对应交易核心应用,另一个号码对应 IDC 机房运维等等。
- 确保资源投入的升级机制。要给到运维和 SRE 授权,当他发现问题不是自己或现有 On-Call 人员能解决的时候,他有权调动其他必要资源投入。
- 与云厂商联合的 On-Call。把云产品和云厂商作为系统的一部分,而不是单纯的第三方。
4)恢复业务
在故障处理过程中采取的所有手段和行动,一切以恢复业务为最高优先级。
当一个问题被定性为故障,这时就要成立 War Room,如果是在办公时间,大家可以聚集到同一个会议室,或者同一块办公区域集中处理;如果是非办公时间,可以是视频、电话或微信会议的方式,形成虚拟的 War Room。但无论是真实还是虚拟的 War Room,根本目的是快速同步信息,高效协作。
有了角色分工,也明确了流程,那整个故障响应是否高效的关键就是沟通机制了。有时涉及的团队和人员比较多,很多具体执行的同事就只顾闷头定位和排查了,往往没有任何反馈,甚至做了很多的操作也是自行决定,不做通报。这时就极有可能衍生故障或者导致故障更大范围的蔓延,这是极为影响协作效率和决策的。
一般要求以团队为单位,每隔 10~15 分钟做一次反馈,反馈当前处理进展以及下一步 Action,如果中途有需要马上执行什么操作,也要事先通报,并且要求通报的内容包括对业务和系统的影响是什么。
所以,除了要做好怎么快速恢复业务,信息同步的及时和透明也非常关键,并且有些安抚措施必须要快速执行到位。故障处理在一定程度上,就不单单是技术团队的问题了,而是需要整个公司都投入资源的。
5)故障复盘
在做故障复盘的时候,首先会结合 Timeline 来做,也就是按照 MTTI、MTTK、MTTF 和 MTTV 先做一个分类;然后针对耗时长的环节,反复讨论改进措施是什么;最后定好责任人和时间点,后续持续跟进执行状况。如果把这些经验再提炼一下,那就是总结出来的故障复盘黄金三问:
- 第一问:故障原因有哪些?
- 第二问:怎么做才能确保下次不会再出现类似故障?
- 第三问:当时如果做了什么,是否可以用更短的时间恢复业务?
通过黄金三问,找到了故障发生的原因,也明确了做什么可以优化,那接下来就是落地。要落地,就要明确到底应该由谁来承担主要的改进职责。具体怎么来做呢?最重要的就是下面这三条故障判定原则。
- 健壮性原则。这个原则是说每个部件自身要具备一定的自愈能力,比如主备、熔断、限流、降级和重试等等。
- 第三方默认无责。例如公有云的各类服务,包括 IaaS、PaaS、CDN 以及视频等等。
- 分段判定原则。当发生衍生故障,或者故障蔓延的原因与触发原因不同时,会将一次故障分段判断。比如大促故障,前半段是由于模型评估不准,没有故障隔离手段造成的,但是后半段,就是因为 DBA 的误操作,以及流程机制不完善造成的。