第二章 实施SLO

作者: Steven Thurgood、David Fergusonwith

编辑: Alex Hidalgo、Betsy Beyer

翻译:张翔

校验:孙建刚,徐德昌,张永福,李昊,石文,李佩京

SLO为服务可靠性设定了一个目标级别。它是可靠性决策的关键因素,所以是SRE实践的核心。无论从哪个角度来看,这都将是本书中最重要的一章。

我们只有具备了一定的理论,设置初始的SLO并细化它们,这个过程才会变得简单。在第一本书第四章中介绍了有关SLO和SLI的相关理论,并对如何使用它们给出了一些建议。

了解了SLO和错误预算这个概念之后,本章提供了一种方法让你开始SLO之旅,以及一些如何进一步迭代的建议。然后,我们将介绍如何使用SLO做出有效的业务决策,并探索一些更高级的使用场景。最后,我们介绍了一些不同场景下开展SLO的案例,以及在特定情况下开展更复杂SLO的指导方案。

 

SRE 需要 SLO的原因

即使在大型研发团队中,工程师也是稀缺资源,工程师的时间应投入到重要服务的核心问题上。工程师应该花时间在功能研发上以便赢得新的客户,还是花时间在提高服务可靠性和可伸缩性上以便让客户满意,这是很难找到平衡点的。谷歌认为一个深思熟虑的SLO是做出决策的关键,这些决策包括了可靠性相关工作,和确定工作优先级排序等内容。

SRE的核心职责不仅仅是将“所有的事情”自动化并随时待命处理故障,他们的日常工作都将按照SLO来开展。确保SLO在短期内是合理的,并且可根据情况适时地调整。甚至可以说,如果没有SLO,就没有SRE。

SLO更像一种工具,可以帮助工程师确定哪个工作优先级更高。 例如,考虑如下两个工作的优先级:将服务自动回滚和切换到备份站点。 通过计算这两个工作的“错误预算”值,我们可以确定哪个工作对用户更有利。有关详细信息,请参阅第37页上的“使用SLO和错误预算进行决策”部分,以及《Site Reliability Engineering》中的“拥抱风险”一章。

 

入门

作为建立基本SLO指标的起点,让我们来假设你的服务是某种形式的代码,它已经被编译和发布,并且运行在用户可以web访问的网络基础设施上。你的系统可能处于如下某个阶段:

• 起步阶段——尚未部署任何内容

• 在生产环境中,当出现问题时,系统的监控会通知您,但是没有正式的目标和没有错误预算的概念,也没有一个明确的正常运行时间

• 有SLO指标,但对其重要性理解不到位,或者不知道如何利用它来进行持续改进。

为了采用基于错误预算的站点可靠性工程方法,您需要达到以下状态:

• 服务的利益相关方认可此SLO

• 服务正常状态下可以达到SLO的要求

• 管理者认可此错误预算并在实际决策中发挥作用

• 有一个完善的SLO过程

否则,您将无法采用基于错误预算的可靠性方法。 SLO合规性成为一个KPI(关键绩效指标)或报告指标了,而不是决策制定工具

 

可靠性指标与错误预算

制定SLO的第一步是讨论SLO是什么,以及它应该包含哪些内容。

SLO为服务客户设定了目标可靠性级别。 超过此阈值,几乎所有用户都应对你的服务感到满意(假设他们对服务的效用感到满意)。低于此阈值,用户可能会开始抱怨或停止使用该服务。最终,用户的快乐才是最重要的 - 快乐的用户使用服务,为您的组织创造收入,减少对您的客户支持团队的抱怨,并向他们的朋友推荐该服务。我们以可靠的服务让客户满意。

顾客满意度是一个相当模糊的概念;我们无法精确衡量它。通常我们对它的了解很少,那么该如何开始呢?

我们的经验表明,100%的可靠性是错误的目标:

• 服务即使使用冗余组件、自动健康检查和快速故障转移,也存在一个或多个组件同时失败的场景,服务的可靠性将低于100%。如果制定的SLO是100%,这件事将不可能实现。(运小白说:泰坦尼克号,有“”永不沉没“”的美誉,底仓有16个水密舱, 任何4个水密舱进水的情况下都不会沉没)

• 即使服务实现了100%的可靠性,但客户也不会体验到100%的可靠性。服务和客户之间的链路长且复杂,链路中的任何一个组件故障都会造成失败败。这也意味着当您的可靠性从99%提高到99.9%到99.99%时,每增加一个9都会增加额外的成本,但客户几乎感受不到。 (运小白说:搜索引擎搜索“运营商故障”即可感受到)

• 如果服务的可靠性是100%的,并希望保持这种可靠性,那么你永远无法更新或改进服务。最大的故障原因就是变化:推出新功能、应用安全补丁、部署新硬件以及扩大规模以满足客户需求都将影响100%的目标。 最终,服务将停滞不前,你的客户将转移到其他地方。(运小白说:对于节日期间没有促销活动的业务来讲,除去偶尔的硬件故障外,那是难得的平静期)

• SLO为100%意味着你只有被动应对。除了对<100%可用性做出反应之外,你实际上无法做任何事情,这是一定会发生的。 100%的可靠性不是工程师要追求的——它应该是运营团队的目标。(运小白说:运维和救火类似,如果消防人员的目标定位不能有任何小火苗,那消防人员估计就会疲于奔命了)

一旦SLO目标低于100%,它就需要由组织中的某个人有权在迭代速率和可靠性之间进行权衡。在小型组织中,这可能是CTO;在更大的组织中,通常是产品所有者(或产品经理)。

 

衡量标准:使用SLI

一旦你认同100%是错误目标,多少才是正确的? 在这里,服务质量指标发挥作用:我们引入SLI的概念,SLI是指服务的质量指标。

虽然计算SLI有多种方法,我们建议SLI为:好的事件数量除以总事件数量。例如:

• 成功的HTTP请求数/总HTTP请求数(成功率)

• 在请求延迟小于100 ms 的成功请求数/总请求数

• 搜索结果数/搜索结果总数,包括那些正常降级的搜索结果

• 使用10分钟以上库存数据的产品搜索的“库存检查计数” 请求的数目/库存检查请求的总数

• “良好用户分钟数” /“用户分钟数”

这种形式的SLI有一些特别有用的属性。 SLI的范围从0%到100%,其中0%表示无效,100%表示无损。 我们发现这个比例是很直观的,这种风格很容易引入错误预算的概念:SLO是一个目标百分比,错误预算是100%减去SLO。 例如,如果您有99.9%的SLO成功率,且在四周内收到的300万个服务的请求,那么在此期间的错误预算为3,000(0.1%)。 如果单个中断导致1,500个错误,则该错误将占错误预算的50%。

此外,使所有的SLI遵循一致的风格以便更好地利用工具:你可以编写报警逻辑、SLO分析工具、错误预算计算和报告,以期望得到相同的输入: 分子、分母和阈值。简化是一个额外的好处。

在尝试首次制定SLI时,将SLI进一步划分为SLI规范和SLI实现是必要的:

SLI规范:

你认为对用户重要的服务结果的评估,与其测量方式无关。

例如:加载小于100毫秒的主页请求比

SLI实现

SLI规范及其测量方法。

例如:

• 加载小于100毫秒的主页请求比,由服务器日志的延迟列进行测量,这种度量方式将遗漏未能到达后端的请求。 (运小白说:遗留有很多个地方都会发生,从用户侧到运营商,从运营商到IDC,从接入层到后端)

• 加载小于100毫秒的主页请求比,由在虚拟机中运行的浏览器中执行JavaScript的探测器测量。 当请求无法到达我们的网络时,此度量将捕获错误,但可能会遗漏仅影响用户子集的问题。(运小白说:例如部分地域/运营商的网络异常,仅通过该方案就无法发现)

• 加载小于100毫秒的主页请求比,通过在主页本身上使用JavaScript进行测量,并将其报告给专门的遥测记录服务。这个度量将更准确地捕获用户体验,尽管我们现在需要修改代码来捕获这些信息,并构建基础设施来进行记录 —— 但这是一个具有自身可靠性要求的规范。 (运小白说:俗称埋点,BAT均有使用,对访问速度优化,可用性监控,地址库优化等均能起到较好的效果)

如你所见,单个SLI规范可能具有多个SLI实现,每个SLI实现在质量(它们如何准确地捕获用户体验),覆盖范围(它们如何捕获所有用户体验)和成本方面都具有自己的优缺点。

您对SLI和SLO的第一次尝试不需要完全正确; 最重要的目标是获得适当的位置并加以测量,并建立反馈机制以便改进。 (我们将在本章的“持续改进SLO目标”中深入探讨这个主题。)

在我们的第一本书中,我们建议不要根据当前的性能选择SLO,因为这可能会导致你执行不必要的严格SLO。虽然这个建议是正确的,但是如果你没有任何其他信息,并且有一个好的迭代过程(我们将在后面介绍),那么你当前的性能是一个很好的起点。但是,当你优化SLO时,不要让当前性能被限制:客户也会期望服务在其SLO上执行,因此如果服务在不到10毫秒的时间内请求成功率为99.999%,任何基于该基线的退化可能让他们不开心。 (运小白说:当前的实际情况是一个参考,而非说目标制定必须以当前值为基础并高于当前值。而且,很多时候,单一目标是能上不能下的,你让用户习惯了这个响应速度,他就无法接受比这个基础值低的服务,这既是门槛也是压力。另外,对单一目标的不断追求,还需要考虑投入产出比。因此这个时候,可以参考下面的建议,从多个维度制定一组SLO。)

要创建第一组SLO,您需要确定对您的服务至关重要的几个关键SLI规范。 可用性和延迟SLO非常常见; 新鲜度,耐用性,正确性,质量和覆盖范围SLO也有它们的位置(我们稍后会详细讨论它们)。(运小白说:大牛们对搜索服务的SLO总结为全,新,快,稳,准)

如果你不知道从哪类SLI开始学习,那么从简单的开始:

• 选择一个要定义SLO的应用程序。如果产品包含许多应用程序,则可以在此之后添加这些应用程序。

• 在这种情况下,明确“用户”是谁。

• 考虑用户与系统交互的常见方式 - 常见任务和关键活动。

• 绘制系统的高级架构图; 显示关键组件、请求流、数据流和关键依赖项。将这些组件分组到下一节中列出的类别中(可能存在一些重叠和歧义; 运用你的直觉,不要让完美成为善意的敌人。) 你应该仔细考虑你选择什么作为你的SLI,但你也不应该过分复杂化。 特别是如果您刚刚开始SLI之旅,请选择相关但易于衡量的系统方面 ,以便可以随时进行迭代和优化。

 

组件类型

开始设置SLI的最简单方法是将系统抽象为几种常见的组件类型。然后,您可以使用我们为每个组件提供的SLI建议列表,来选择与您服务最相关的SLI:

请求驱动

用户创建某种类型的事件并期望响应。 例如: 这可以是HTTP服务,其中用户与浏览器或移动应用程序的API交互。

管道

一种系统,它将记录作为输入,对其进行转变,并将输出放在其他位置。 这可能是一个在单个实例上实时运行的简单过程,也可能是需要花费数小时的多阶段批处理过程。 例子包括:

• 一种定期从关系数据库中读取数据并将其写入分布式哈希表以优化服务的系统

• 一种将视频从一种格式转换为另一种格式的视频处理服务

• 一种从多个源读取日志文件以生成报告的系统

• 一种从远程服务器提取指标并生成时间序列和报警的监控系统

存储

接收数据(例如字节、记录、文件、视频)并使其在以后可以被检索的系统。

 

案例

一个简化过的手机游戏架构,如图2-1所示。

第二章 实施SLO

图2-1 一个手机游戏的架构示例

在用户手机上运行应用程序与云中运行的HTTP API交互。API将状态更改并写入永久存储系统。一个管道定期运行这些数据,来生成今天、本周和所有时间的高分排行。这些数据被写入一个单独的排行榜数据存储,可以通过移动应用程序和网站获得结果。用户可以通过API和网站将游戏中使用的自定义头像上传到用户数据表。

鉴于此设置,我们可以开始考虑用户如何与系统交互,以及采用哪种SLI衡量用户体验。

这些SLI中有些可能存在重叠:请求服务具有正确性SLI,管道具有可用性SLI,并且持久性SLI可能被视为正确性SLI的变体。 我们建议选择少数(五个或更少)SLI类型,这些类型代表了客户最关键的功能。。

为了捕获典型的用户体验和长尾,我们还建议使用多个等级的SLO。例如,如果90%的用户请求在100毫秒内返回,但剩下的10%用户需要10秒,这部分用户将不满意。 延迟SLO可以通过设置多个阈值来捕获此用户群:90%的请求快于100毫秒,99%的请求快于400毫秒。 这个原则适用于所有的SLI -- 这些SLI的参数用来衡量用户的满意程度。

表2-1为不同类型的服务提供了一些常用的SLI。

表2-1 不同类型组件常用的SLI

服务类型

SLI类型

描述

请求驱动

可用性

成功响应的请求比例。

请求驱动

延迟

比某些阈值快的请求比例。

请求驱动

质量

如果服务在过载或后端不可用时正常降级,则需要测量在未降级状态下提供服务的响应比例。 例如,如果用户数据存储不可用,但使用通用图像游戏仍可玩。

管道

新鲜度

最近更新的数据比例超过某个时间阈值。 理想情况下,此指标会计算用户访问数据的次数,以便最准确地反映用户体验。

管道

正确性

正确输出值的比例。

管道

覆盖范围

对于批处理,处理超过某个目标数据量的作业比例。

对于流处理,在某个时间窗口内成功处理的传入记录比例。

存储

耐用性

可以成功读取的记录所占的比例。特别注意持久性SLI:用户想要的数据可能只是存储数据的一小部分。例如,如果你在过去10年里有10亿个记录,但是用户只需要今天的记录(但这些记录不可用),那么即使他们的数据几乎都是可读的,他们也会不高兴。

 

从SLI理论到SLI实践

第一次SLI实践可以考虑选择一个资源需求相对较少的项目。比如有如下几个项目可供选择:web日志服务器的SLI项目,这个项目我们不需要准备什么;对监控系统进行SLI项目实践,但是这需要几周的时间准备,而JavaScript的项目则会需要几个月的时间。在这种情况下请使用web服务器的日志来作为第一个SLI实践的工程。

衡量SLI需要足够指标:可用性指标(成功率和失败率); 慢请求延迟(请求的响应时间)。 这些指标可能需要你重新对Web服务器进行配置才能获得。 如果是基于云服务的Web,这些指标可以在监控仪表盘中看到。

在这个案例中我可选择的SLI指标有很多,每个指标都有自己的优缺点。 以下部分详细介绍三种典型的SLI指标的应用。

API和HTTP服务的可用性指标和慢请求延迟指标

请求是否成功可以基于HTTP的返回码。5XX就代表请求失败,会降低服务的SLO,其他响应码代表成功。 可用性的SLI是指请求成功率;慢请求延迟的SLI是指在给定请求响应时间阈值下的请求成功率。

SLI应该是具体明确并可测量的。总结“衡量标准:使用SLI”中的提供的潜在候选列表,SLI可以使用以下的一个或多个数据来源:

  • 应用服务器日志

  • 负载均衡监控

  • 黑盒监控

  • 客户端插件

我们的例子采用负载均衡监控,因为这些指标已经是可用的,并且数据信息比采用“应用服务器日志”更真实反应用户体验的SLI。(运小白说:采用负载均衡的数据,是因为接入层记录的耗时,是一个用户请求在整套系统所有模块处理耗时和所有网络传输耗时的总和,因此更加真实的反应用户的体验,且和客户端插件相比,实施成本相对较低。但该部分耗时,并不包含从用户端到IDC这段的耗时)

管道数据延迟率,范围覆盖率和准确率

使用管道系统管理一个排行榜时,它会记录一个包含有数据更新的时间戳标签。下面是我们进行SLI实践的例子:

  • 在排行榜上周期性的运行一个进程用于查询有多少次记录被更新和总共有多少个记录。这两个指标同样重要。

  • 在用户请求数据时默认为请求增加一个时间标签,排行榜服务收到客户端请求后会检查这个标签并将请求计数器+1, 如果数据超出了预定义的阈值,则将配置另一个用于记录超时的计数器数字+1。(运小白说:在一个数据流中各个环节或者关键环节中添加时间戳后,可以在监控,性能优化,故障定位等多种场景中使用)

以上两个步骤的数据要求都在客户端实现 。这个指标与用户体验密切相关。

为了计算我们覆盖率的SLI,我们的管道输出了它应该处理的记录数和它成功处理的记录数。此度量标准可能会遗漏由于管道配置错误而未记录的数据。

我们采用如下方法来评估准确率:

  • 将已知的数据作为输入写入系统,计算输出与期望值匹配率。

  • 基于默认管道的输入输出结果作为基准,计算此管道在相同输入下的输出与前者匹配的程度(这个方法可能并不适合所有的管道系统)。

我们的案例是为一个需要人工管理的数据库建立指标为准确率的SLI。所有的数据的输入都是合法的,通过管道系统输出结果, 计算输出的准确率。为了使指标能够很好的反应用户体验,我们需要确保人工输入的数据和用户真实数据是一致的。(运小白说:这段看似简单,却是经验的分享。举一个具体的例子来让大家更深刻的理解,以计算服务为例,将已知的数据作为输入写入系统,你可以每分钟输入一个不变的数,然后让系统去计算一定时间的和值,从而度量计算服务的SLI。进阶的话,就是每分钟输入的是变化的数,从而计算和值,均值,最大值,最小值,那变化的数用什么呢,一般就是当前的分钟数)

 

SLI的计算

图2-2展示的是用白盒监控系从示例程序的各个组件中收集指标的过程。

第二章 实施SLO

图2-2 我们的监控系统是如何收集SLI指标的

给出一个示例来说明我们是如何使用监控系统中的指标来计算启动器的SLO指标的,以便读者可以更好的理解。虽然我们在案例中只使用了可用性和慢查询延迟指标,但是同样的思路也适用于其他潜在的SLO指标的计算。系统使用度量标准的完整列表,请参阅附录a。我们的案例都使用普罗米修斯监控系统进行数据采集(Prometheus notation)。

负载均衡指标

后端的请求返回码为500的数量(“api” or “web”):

 

http_requests_total{host="api", status="500"}

总延迟,作为累积直方图;每个柱状图(bucket)表示计算花费少于或等于该时间的请求数量:

 

http_request_duration_seconds{host="api", le="0.1"}

http_request_duration_seconds{host="api", le="0.2"}

http_request_duration_seconds{host="api", le="0.4"}

一般来说,计算得到慢请求数要比用直方图估计得到的慢请求数更加精准。但是,由于有些信息是拿不到的,所以最终使用监测系统提供的直方图。另一种方法是根据负载均衡配置中的各种慢请求阈值(例如,阈值为100毫秒和500毫秒)来计算慢请求数量。这种方式需要对监控的配置进行修改,所以会更复杂但是会更准确。

 

http_request_duration_seconds{host="api", le="0.1"}

http_request_duration_seconds{host="api", le="0.5"}

计算SLI

使用前面的指标,我们可以计算前七天的当前SLI,如表2-2所示。

表2-2 过去七天的SLI计算

可靠性

sum(rate(http_requests_total{host="api", status!~"5.."}[7d])) / sum(rate(http_requests_total{host="api"}[7d])

延迟

histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[7d])) histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[7d]))

 

利用SLI计算初始 SLO

我们可以将这些SLI划分为可管理的数字(例如,两个重要的可用性数据,或最多50 ms的延迟)来获得我们的起始SLO。

例如,超过四周,API指标显示:

  • 总请求数:3663253

  • 总成功请求数:3,557,865 (97.123%)

  • 90%的延迟: < 432 ms

  • 99%的延迟: < 891 ms

我们为其他SLI重复此过程,并为API创建一个SLO,如表2-3所示。

表2-3 API的建 SLO

SLO类型

目的

可用性

97%

延迟

90% 的请求 < 450 ms

延迟

99% 的请求 < 900 ms

附录A提供了SLO文档的完整示例。 本文档包含SLI实现,为简洁起见,我们在此省略。

根据所提出的SLI,我们可以计算这四周的错误预算,如表2-4所示。

表2-4 过去四周错误预算

SLO

允许失败数

97%的可用性

09,897

90%的请求快于450ms

366,325

99%的请求快于900ms

36,632

 

选择合适的时间窗口

可以在不同的时间间隔上定义SLO,并且可以使用滚动窗口或周期对齐窗口(例如,一个月)。选择时间窗口时需要考虑几个因素。

滚动窗口与用户体验更紧密地联系在一起:如果你在一个月的最后一天发生大量中断,则你的用户在下个月的第一天不会突然忘记它。 我们建议将这段时间定义为整数周,以便它始终包含相同数量的周末。 例如,如果你使用30天的窗口,则某些时段可能包括四个周末,而其他时段包括五个周末。 如果周末流量与工作日流量明显不同,你的SLI可能会因为无趣的原因而有所不同。

周期窗口与业务规划和项目工作更紧密地结合在一起。例如,你可以每个季度评估SLO,以确定下一个季度项目人员的重点工作。周期窗口还引入了一些不确定性因素:在季度中期,你不可能知道在本季度余下的时间里会收到多少请求。因此,在季度中期做出的决定必须推测系统将在本季度剩余时间内花费多少错误预算。

更短的时间窗口可以让你更快地做出决策:如果你错过了前一周的SLO,那么小的更正 - 例如优先考虑相关错误 - 可以帮助避免未来几周的SLO违规。

对于更具战略性的决策,更长的时间周期更好:例如,如果你只能选择三个大型项目中的一个,那么你最好转移到高可用性分布式数据库,自动执行部署和回滚过程,或者在另一个部署重复堆栈区。你需要超过一周的数据来评估大型多季度项目; 所需的数据量与建议修复它的工程量大致相当。

我们发现为期四周的滚动窗口是一个很好的通用间隔。我们每周任务优先级总结和每季度的项目规划总结报告刚好补充这一时间段。

如果数据源允许,则可以使用这个建议的SLO来计算在此期间的实际SLO性能:如果根据实际测量设置初始SLO,则按此设计。但我们也可以收集关于分布的有趣信息。在过去的四个星期内,有哪天我们的服务没有达到标准? 这些天与实际事件有关联吗? 在那些日子里,有没有(或者应该)采取一些行动来应对这些事件?

如果没有日志、度量或任何其他历史性能来源,则需要配置数据源。例如,作为HTTP服务的基本解决方案,你可以设置远程监视服务,对HTTP服务定期的执行某种健康检查(ping或HTTP GET),并报告请求成功的数量。许多在线服务可以轻松实现这一解决方案。

 

获得所有利益相关者同意

为了使提议的SLO有用和有效,你需要让所有利益相关者同意它:

• 产品经理必须同意这个阈值 ——低于这个值的性能无法令人接受,需要花费时间来修复。

• 产品开发人员需要同意,如果错误预算已用尽,他们将采取一些措施来降低用户的风险,直到服务重新回到错误预算中(如第31页的“建立错误预算策略”中所述)。

• 负责维护这个SLO生产环境的团队已经同意并一致认为,不需要付出巨大的努力、过度的辛劳——这对团队和服务都是不利的。 一旦所有这些观点都达成一致,最难的部分就完成了。你已经开始了SLO之旅,剩下的步骤需要从这个起点迭代。

你需要设置监控和报警来监控SLO,(请参阅第5章),以便工程师发现问题。

 

建立错误预算策略

获得SLO后,你可以使用SLO来获取错误预算。 要使用此错误预算,你需要一个策略,描述当你的服务超出预算时要执行的操作。

获得所有关键的利益相关者(产品经理、开发团队和SRE)批准的错误预算策略,是对SLO是否适合目的良好测试:

• 如果SRE认为需要付出更多的工作才能保证SLO,那么他们可以提出放宽SLO的要求。

• 如果开发团队和产品经理认为,他们必须投入更多的资源来修复系统,这将导致特性发布速度低于可接受的水平,那么他们也可以争取放宽目标值。记住,降低SLO也会降低SRE响应的情况数量;产品经理需要对此做权衡。

• 如果产品经理认为,在错误预算策略提示任何人解决某个问题之前,SLO将给大量用户带来糟糕的体验,那么SLO可能不够紧凑。

• 如果所有三方都不同意执行错误预算策略,那么你需要迭代SLI和SLO,直到所有利益相关者都满意为止。决定如何前进,以及做出决定需要什么:更多的数据?更多的资源?还是对SLI或者SLO进行修改?

当我们讨论强制执行错误预算时,我们的意思是一旦你耗尽了错误预算(或者接近于耗尽它),你应该采取措施来恢复系统的稳定性

要制定错误预算执行决策,你需要从书面策略开始。 此策略应涵盖服务在给定时间段内消耗全部的错误预算时必须采取的具体操作,并指定谁将采取这些操作。 共同所有者和行动包括:

• 开发团队将过去四周内与可靠性问题相关的bug放在了首位。

• 开发团队专注于可靠性问题,直到系统处于SLO范围内。 功能迭代可以推迟。

• 为了降低更多停机导致的风险,冻结生产系统的变更,直到有足够的错误预算来恢复变更。

有时候,服务会消耗掉整个错误预算,但并不是所有利益相关者都同意制定错误预算策略是合适的。如果发生这种情况,你需要返回到错误预算策略审批阶段。

 

记录SLO和错误预算策略

一个SLO应记录在一个突出的位置,其他团队和利益相关者可以审查它。该文件应包括以下信息:

• SLO的作者,审核人(检查技术准确性)和审批人(谁做出了关于它是否是正确的SLO的商业决策)。

• 批准的日期,以及下次审核的日期。

• 为读者了解相关背景的简要说明。

• SLO的细节:目标和SLI实现。

• 关于如何计算和使用错误预算的详细信息。

• 这些数字背后的基本原理,以及它们是否来自实验或观察数据。 即使SLO完全是临时的,也应记录这一事实,以便未来阅读文档的工程师不会根据临时数据做出错误的决定。 你查看SLO文档的频率取决于SLO文化的成熟度。

在开始时,你应该经常审查SLO (例如每个月)。 一旦SLO变得更加符合实际,你可以降低评审频率为每季度或更低。

制定错误预算策略,还应包括以下信息:

• 策略的制定人、审核人和审批人

• 批准的日期,以及下次审核的日期

• 编写说明文档

• 应对错误预算耗尽时采取的行动

• 如果在某种情况下商定的策略发生分歧,则将问题升级

•让有经验的工程师对错误预算进行审核

有关SLO文档和错误预算策略的示例,请参阅附录A。

 

仪表盘和报表

除了已发布的SLO和错误预算,及说明文档之外,还应有一个报表和仪表盘进行展示。(运小白说:通过仪表盘/大屏以及背后的存储系统,记录,展示和分析长期的SLO,从而才能帮助团队更好的发展,减少犯同样的错误)

图2-3中的报表显示了几种服务的总体合规性:它们是否满足前一年的所有季度的SLO(括号中的数字表示满足的目标数量,以及目标总数),以及他们的SLI相对于上一季度和去年同一季度是否呈上升趋势或下降趋势。

第二章 实施SLO

图2-3 SLO合规报告

使用仪表盘来显示SLI的趋势也是很有用的。 这些仪表盘显示你是否以高于平常的速率消费预算,或者是否存在需要特别关注趋势。

图2-4中的仪表盘显示了一个季度的错误预算,在该季度的中间部分,我们看到单个事件在两天内消耗了大约15%的错误预算。

第二章 实施SLO

图2 - 4 错误预算仪表板

错误预算对于量化这些事件很有用——例如,“这次宕机消耗了我季度错误预算的30%”,或者“这是本季度排名前三的事件,根据它们消耗了多少错误预算来排序”。

 

持续改进SLO目标

每项服务都可以从持续改进中受益。 这是ITIL的核心服务目标之一。 例如:

在你提高SLO目标之前,你需要拥有用户对服务满意度的信息来源。 有很多选择:

  • 人工发现的服务不可用次数、公共论坛上的帖子、故障单和投诉电话

  • 社交媒体上的用户反馈

  • 用插件定期对用户的满意度进行采样

  • 调查问卷进行用户调查和采样

最佳的方法取决于你的服务,我们建议从成本较低的渠道开始。让你的产品经理把可靠性纳入到他们与客户关于定价和功能的讨论中,这会是一个很好的开始。

 

提高SLO质量

记录人工检测到的服务不可用次数, 其他相关网站支持票数也可以计算在内,检查这些数据是否与错误预算的变化趋势相关。 同时检查这短时间内SLI和SLO的变化趋势。如果你擅长统计分析,Spearman相关系数是量化这种关系的有效方法。

图2-5显示了每天增加的支持票的数量与当天错误预算的关系。虽然不是所有的支持票都与可靠性问题相关,但支持票与错误预算之间是存在相关性。我们看到两个异常值:一天只有5张票,损失了10%的错误预算;一天有40张票,没有损失任何错误预算。这两个异常值都需要进一步追查。

第二章 实施SLO

图2 - 5 每天增加的支持票的数量与当天错误预算的关系

如果支持票未在SLI或SLO中体现,或者用户关注的问题并没有在指标中体现,说明指标覆盖率存在问题。 这种情况完全正常,符合预期。 你的SLI和SLO应随着时间的推移而发生变化,因为服务的实际情况会发生变化, 不要畏惧对它们进行改进!

如果你的SLO或SLI覆盖率不高,你可以采取多种方案:

修正SLO

如果你的SLI显示现在出问题了,但是你的SLO没有异常,你可能需要更加严格的SLO。

  • 如果该时间段内发生的问题比较严重,通过SLI计算SLO应该出现异常的时间段。调整SLO之后,把这个新的SLO应用到SLI的历史数据上,看看这个调整会发现什么问题。如果发现严格的SLO会不断地对不重要的事件作出响应,那么这个修正毫无意义。

  • 同样地,对于SLO误报的情况,考虑放宽SLO。

如果在任一方向上修正SLO会导致误报或漏报,那么你还需要修正SLI实现。

修正SLI实现

有两种方法可以修正SLI实现: 要么将采集点更靠近用户以提高度量精准度;要么提高覆盖率,从而获得更高的用户交互比例。例如:

  • 在负载均衡或客户端上测量成功率/延迟,而不是在服务器上测量。

  • 更多的功能检测任务,或者在所有客户端通过JavaScript探测,而不仅仅是使用简单的HTTP GET请求来衡量可用性。

制定一个高标准的SLO

有时你需要更严格的SLO才能让用户满意,但改进产品以满足SLO需要一些时间。 如果你实施更严格的SLO,你将永久地脱离SLO并受到错误预算政策的约束。 在这种情况下,你可以将高标准的SLO作为期望值,与当前SLO一起进行追踪和对比。 通过这种方式,你可以掌握与高标准SLO之间的差距,却不会一直处于高压状态。

迭代

有许多不同的迭代方法,评审会议可以帮你找到许多潜在改进点。选择成本最低的方法,特别是在最初的几次迭代中,错误常常出现在贪图更快,更便宜方面; 这样做可以减少指标的不确定性,并帮助你确定是否需要更昂贵的指标。 根据需要进行多次迭代。

 

使用SLO和错误预算进行决策

一旦你制定了SLO,你就可以使用它们进行决策。

当你没有达到SLO,也就是说已经用尽了错误预算,这时面对的首要问题是要做什么?如前所述,错误预算策略会告诉你应该做什么。 常见策略包括降级,直到服务再次处于SLO中;或者花费时间去处理问题以提高服务的可靠性。

在特殊情况下,团队可以对外宣布处于紧急状态,取消所有外部需求,直到服务满足退出条件 (退出条件通常指服务处于SLO中,并且短时间内SLO不会出现问题)。我们可以使用改进监控,改进测试,消除系统的依赖关系,或重新调整架构以排除已知的故障类型等方法。

你可以根据消耗错误预算的比例来确定事件的规模,并使用这些数据来识别最关键的故障,这些故障需要更深入的追查。

例如,假设新版本API的发布导致100% NullPointerExceptions,系统直到四小时后才可以恢复。检查服务的原始日志表明该问题导致了14,066个错误。 使用制定的97%的SLO和109,897个错误预算的标准来计算,这个故障使用了13%的错误预算。

或者,数据库出现问题,而从备份数据恢复需要20小时。基于历史流量估算中断导致了72,000个错误,占错误预算的65%。

想象一下,假设五年内只有一次服务器故障导致数据库异常,但通常每年会有两到三个版本被回退。 可以估计发布新版本导致的错误预算是数据库故障的两倍。 这些数字表明,投入资源来解决版本问题比调查服务器故障更有益处。

如果服务运行完美且几乎不需要任何监督,并且做到了服务的故障管理和高级别的监督,那么你可以减少对此服务的SLO实施。因此,你可以将精力集中在其他需要更多SRE支持的系统上。

表2-5 提供了基于三个关键维度决策矩阵:

  • SLO指标

  • 维护服务所需要的工作量

  • 客户对服务的满意程度

表2-5 SLO决策矩阵

SLO

工作量

客户满意度

行动

Met

Low

High

a.提高发布的可靠度和部署的速度

b.退出参与,并将工程重点放在需要更高可靠性的服务上

Met

Low

Low

收紧SLO

Met

High

High

如果报警产生误报,则降低灵敏度。 否则,暂时放松SLO,减少琐事,并修复产品,或通过自动化处理故障来缓解

Met

High

Low

收紧SLO

Missed

Low

High

放宽SLO

Missed

Low

Low

增加报警灵敏度

Missed

High

High

放宽SLO

Missed

High

Low

减少琐事,修复产品或通过自动化处理故障来缓解

 

SLO进阶

一旦你拥有成熟的SLO和错误预算的氛围,下一步要做的就是继续改进和完善如何度量服务的可靠性。

 

模拟用户

SLO最终应该以改善用户体验为中心。 因此,你应该以用户为中心制定SLO。

你可以仿照用户典型流程来评估用户的体验 (典型流程是指一系列任务的集合,包括了用户体验核心部分,也是服务的重要方面)。 例如,对于在线购物体验,用户典型流程包括:(运小白说:大牛总结的电商典型流程是首页-搜索-商详-购物车-下单-支付)

  • 搜索产品

  • 添加购物车

  • 完成购买

这些肯定不能很好地映射到现有的SLI;每个任务都需要多个复杂的步骤,这些步骤可能在任何时候都会失败,并且从日志中推断这些操作的成功(或失败)非常困难。 (例如,如何确定用户在第三步失败了?可能他们只是被分散了注意力)。然而,你需要定位到故障发生的原因是什么,因为这是服务可靠性的一部分。

一旦确定了用户最关心的问题,就可以通过监测典型流程来解决上述问题。 你可以通过将不同的日志事件连接在一起,使用高级JavaScript探测,使用客户端检测或使用其他一些过程来度量它们。 一旦你可以定位一个问题,它就变成了另一个SLI。你可以和现有的SLI和SLO一起追踪。 用户关键流程可以在不影响精度的情况下提高你的召回。

 

分级的重要性

并不是所有的请求都是平等的。虽然来自app的HTTP请求——检查帐户通知(其中通知是由每日的管道生成的)对用户很重要,但广告客户与账单相关的请求更重要。

我们需要一种方法来对请求进行分类,可以使用“bucketing”来完成此操作 - 也就是说,为SLI添加更多标签,然后对不通的标签制定不同的SLO指标。 表2-6显示了一个示例。

表2-6 分级分配SLO

客户层

可用性SLO

付费用户

99.99%

免费用户

99.9%

你还可以按照响应对请求进行分类,如表2-7所示。

表2-7 按照响应进行分类

响应能力

延迟SLO

交互式(即阻止页面加载的请求)

90%的请求在100毫秒内完成

CSV下载

90%的下载在5秒内开始

如果你可以为每个用户制定SLO,那么你就可以在任何时间内得到处于SLO合理范围内的用户数量。请注意,这个数字是有大量噪音——请求数量非常少的客户要么拥有100%的可用性(因为他们足够幸运地没有遇到故障)要么拥有非常低的可用性(因为他们经历的一个失败会是相当大的百分比,因为请求基数少 )。单个客户可能会因为一些低级的原因而无法满足他们的SLO。但是总的来说,跟踪这个指标是非常有用的。(运小白说:关于分级,我记忆中最深刻的是以前一个同事的总结,30%的资源,支持了10%的流量,提供了5%的收入,因此这类资源必须要优化)

 

依赖关系建模

大型系统有许多组件。单个系统可能有表示层、应用层、业务逻辑层和数据持久层。每一层都可能包含许多服务或微服务。

虽然你最关心的是系统的SLO实现,但SLO也可以作为提高系统各组件间可靠度的有用方法。

例如,系统某个组件被过度依赖,那么它的可靠性保障应尽可能放到*。相应组件的团队也应有SLO。

如果某些组件可靠性存在客观限制,则SLO应该可以将该限制表现出来。如果这个组件不能满足系统的可靠性要求,要么改进它,要么使用其他组件代替他或进行主动防御(比如:添加缓存,预存储和计算,优雅降级等)。

你也可以尝试用数学方法解决这些问题。例如:如果在单个区域内有一个可用性为99.90%的服务,但你需要99.95%的可用性,则在两个区域中部署该服务就可以解决这个需求。两个服务同时发生故障的概率非常低,此时服务的可用性为99.9999%。然而,这种情况的假设前提是两区域服务完全独立,但这几乎不可能。应用程序的两个实例将具有共同的依赖和故障模式,无论如何精心设计和管理,都可能会导致两个服务同时异常。除非将这些依赖项和故障模式都被枚举出来,否则任何此类计算都具有欺骗性。

当故障是由其他团队负责的组件引起的,以下两种思路可以用于解决SLO的问题:

  • 你的团队还应该继续开展发布新版本,不要把过多时间用于可靠性相关工作,因为不是你系统引起的问题

  • 你应该制定故障隔离策略,以便最大程度地降低未来可能由此组件引起的服务故障的可能性,无论此组件故障的原因是什么

第二种方法将使你的用户更快乐。你可以灵活地运用这个原则。根据停机和依赖关系的性质,冻结更改可能不实际。确定最适合你服务及其依赖项的决定,并将此决定记录在你的错误预算策略中。有关如何在实践中工作的示例,请参阅附录B中的错误预算策略示例。(运小白说:这个问题非常典型,大家都可能会碰到,我使用你的服务,你应该保障你服务承诺的可用性,而不应该是我来解决这个问题;本文给出了另外的一种思路,添加缓存,预存储和计算,优雅降级,多活,多机房部署等来保障自身服务的稳定性,因此下次遇到这类问题,希望大家可以尝试一下这些方式。另外,高内聚低耦合固然重要,但是也不要太过极端,觉得别人的东西都不靠谱,只有全部自己做才放心,很多时候,把一些依赖的服务放到手里独立部署,你觉得稳定性提升很多,其实,那只是集群拆分压力减小后的一种表象,平时很少出问题,因此你也会放松警惕,另外,加之业务众多,每个业务投入的精力也较为有限,一旦出现问题,通常难以应对)

 

放宽SLO,进行试验

如果你想对服务进行可靠性的相关试验以便了解指标(例如,增加页面加载时间的延迟)的变化对用户体验的影响程度(例如,完成购买的用户百分比)。我们建议,只有当你确信自己有足够的错误预算时,才进行这类操作和分析。由于延迟、可用性、客户、业务领域和竞争(或缺乏竞争)这些因素之间有许多微妙的相互作用。故意影响顾客体验的决策需要深思熟虑。

虽然这种方法的影响听起来十分可怕,因为没有人想失去用户。但通过这种方法,你可以将得到的结论用于服务的改进,从而在未来让服务拥有更好的性能,从而获得更多的用户。这种方法还可以让你在统计学上获得关键业务度量(例如,销售额)和可靠性指标(例如,延迟)之间的关系。如果是这样,你就获得了非常有价值的数据,这些数据可以帮助你做成做出重大决策。

这个尝试不应该是一次性的。随着你的服务的发展,你的客户的期望也会随之改变,确保它们之间的关系是实时有效的。

这种尝试获得的关系也可能存在风险,因为你可能会误解你得到的数据。例如,如果你人为地将页面加载时间增加了50毫秒的延迟,但是并没有发现相应的损失,那么你可能会得出这样的结论: 延迟的SLO太严格了。然而,你的用户可能是不满意,只是缺乏可替代的产品,用户别无选择。一旦出现竞争对手,你的用户就会流失。一定要保数据的正确性,并采取适当的预防措施。

 

结论

本书的每个案例都有SLO理论的影子。既然你已经阅读了这一章,我们希望能够意识到,即使是形式化的SLO(它清楚地向用户传达了你的承诺)也提供了一个清晰的框架来分析你系统表现。在服务未能满足期望时,你还可以用此SLO确定可采取的补救措施。

总结:

  • SLO是衡量服务可靠性的工具

  • 错误预算是一种工具,它可以帮助你平衡可靠性和其他日常工作的精力,同时也是判定工作优先级的好方法

  • 你应该立即使用SLO和错误预算

有关SLO文档和错误预算策略的示例,请参阅附录 A和B。