瓶颈 #05:弹性和可观察性

服务中断;生产事故会降低声誉和收入

2023 年 8 月 22 日


Photo of Punit Lad

Punit Lad 是 Thoughtworks 的技术主管和基础设施工程师。他领导团队并为跨行业、规模和成熟度的组织的客户提供建议。作为思想伙伴,他与客户合作塑造愿景和战略,作为一名开发人员,他喜欢通过实施解决方案以及构建产品和平台来实现他们的战略目标。最近,Punit 对开发者体验产生了浓厚的兴趣,并将产品思维应用于提高开发团队的效率和影响力。

Photo of Carl Nygard

Carl Nygard 是 Thoughtworks 的技术总监。Carl 拥有超过 20 年的经验,领导团队从初创企业到大型企业,为 GIS/遥感、供应链、实时控制、在线教育、零售和政府构建解决方案。他与组织合作制定技术战略,通过优化的软件交付实践实现业务成果。


可用性是最重要的功能

-- Mike Fisher,Etsy 前 CTO

“我被击倒,但我再次站起来……”

-- Tubthumping,Chumbawumba

每个组织都关注弹性。关键问题是何时关注。

初创企业往往只在系统出现故障时才解决弹性问题,通常采取非常被动的做法。对于规模化企业来说,过度的系统停机时间代表着组织的重大瓶颈,既来自恢复功能所付出的努力,也来自客户不满意的影响。

为了克服这一点,弹性需要融入业务目标,这将影响业务系统的架构、设计、产品管理,甚至治理。在本文中,我们将探讨弹性和可观察性瓶颈:如何识别其出现,如何意识到它已经出现,以及如何克服瓶颈。

你是如何陷入瓶颈的?

初创企业的首要目标之一是将初始产品推向市场。让产品尽可能多地出现在用户面前,并从他们那里获得反馈,通常是最高优先级。如果客户使用您的产品并看到它提供的独特价值,您的初创企业将开拓市场份额并拥有可靠的收入来源。然而,实现这一目标往往会以牺牲产品弹性为代价。

初创企业可能会决定跳过自动化恢复流程,因为在小规模的情况下,组织认为可以通过了解系统的开发人员来提供弹性。事件以被动的方式处理,解决方案是手动完成的。可能的解决方案可能是启动另一个实例来处理增加的负载,或者在服务出现故障时重启服务。您的第一批客户甚至可能意识到您缺乏真正的弹性,因为他们会遇到系统停机。

在我们的一项规模化企业参与中,为了快速将系统投入生产,客户降低了集群中健康检查机制的优先级。开发人员成功地管理了几次必要的启动过程。为了进行重要的演示,决定启动一个新的集群,这样就不会有外部因素影响系统性能。不幸的是,人们忽略了主动管理集群中运行的所有服务的运行状况。演示在系统完全运行之前就开始了,系统的一个重要组件在潜在客户面前发生了故障。

从根本上说,您的组织已经做出了明确的权衡,优先考虑用户界面功能而不是自动化弹性,赌博认为组织可以通过人工干预从停机中恢复。在初创企业处于可管理规模时,这种权衡可能是可以接受的。但是,当您经历高速增长并从初创企业转变为规模化企业时,缺乏弹性被证明是一个扩展瓶颈,表现为服务中断的发生率越来越高,这转化为 DevOps 团队职责中的运维方面的工作量增加,降低了团队的生产力。影响似乎突然出现,因为相对于客户群的增长,影响往往是非线性的。最近可控的东西突然变得非常有影响力。最终,系统的规模会产生超出团队能力范围的手动工作,这会影响客户体验。生产力下降和客户不满意的结合导致难以克服的瓶颈。

那么问题是,如何知道我的产品是否即将遇到扩展瓶颈?此外,如果我知道这些迹象,如何避免或跟上我的规模?当我们描述我们在客户身上遇到的常见挑战以及我们发现最有效的解决方案时,我们将努力回答这个问题。

接近扩展瓶颈的迹象

在业务规模快速变化的环境中运营总是很困难。过早地投资处理高流量会浪费资源。投资过晚意味着您的客户已经感受到扩展瓶颈的影响。

为了将您的运营模式从被动转变为主动,您必须能够以足以支持重要业务决策的置信度预测未来的行为。数据驱动的决策始终是目标。关键是找到领先指标,这些指标将指导您为瓶颈做好准备,并希望避免瓶颈,而不是对已经发生的瓶颈做出反应。根据我们的经验,我们发现了一组与您接近此瓶颈的常见先决条件相关的指标。

弹性不是首要考虑因素

这可能是最不明显的迹象,但可以说是最重要的。弹性被认为纯粹是技术问题,而不是产品的特性。它被新功能和增强功能降级。在某些情况下,它甚至不是需要优先考虑的问题。

这里有一个快速测试。倾听您团队中发生的各种讨论,并注意讨论弹性的背景。您可能会发现它没有包含在每日站立会议中,但它确实出现在开发人员会议中。当开发团队不负责运营时,弹性实际上被隔离了。在这种情况下,请密切注意如何讨论弹性。

缺乏对弹性的关注的证据通常是间接的。在一个客户那里,我们看到它以技术债务卡的形式出现,这些卡不仅没有被优先考虑,而且成为一个不断增长的列表。在另一个客户那里,运维团队的积压工作完全由客户事件组成,其中大部分事件涉及系统无法启动或无法处理请求。当弹性问题不是团队积压工作和路线图的一部分时,您将有证据表明它不是产品的核心。

手动解决弹性(反应式手动弹性)

您的组织如何解决服务中断可能是您的产品能否有效扩展的关键指标。我们在这里描述的特征从根本上来说是由缺乏自动化造成的,导致过多的手动工作。服务中断是通过开发人员重启解决的吗?在高负载下,是否需要协调来扩展计算实例?

总的来说,我们发现这些方法不遵循可持续的运营实践,并且对于下一次系统中断来说是脆弱的解决方案。它们包括权宜之计,这些权宜之计缓解了症状,但从未真正以允许未来弹性的方式解决问题。

系统所有权定义不明确

当您的组织快速发展,开发新的服务和功能时,服务生态系统中的关键部分,甚至基础设施,可能会变得“孤立”——没有明确的运营责任。因此,生产问题可能在客户做出反应之前一直没有被注意到。当它们发生时,排查问题需要更长的时间,这会导致解决中断的延迟。在努力找到责任方时,问题在团队之间来回弹跳,导致解决问题的延迟,浪费了每个人的时间。

这个问题并不局限于微服务环境。在一个项目中,我们目睹了类似的情况,一个整体架构缺乏对系统部分的明确所有权。在这种情况下,所有权问题不明确源于“泥球”整体架构中缺乏明确的系统边界。

忽略分布式系统的现实

开发有效系统的部分内容是能够定义和使用抽象,使我们能够简化复杂的系统,使其真正适合开发人员的思维。这使开发人员能够做出有关未来更改的决策,这些更改对于向企业交付新价值和功能是必要的。然而,就像所有事情一样,人们可能会走得太远,没有意识到这些简化实际上是隐藏了影响系统的关键约束的假设。借鉴分布式计算谬误

  • 网络不可靠。
  • 您的系统受光速的影响。延迟永远不会为零。
  • 带宽是有限的。
  • 网络本身并不安全。
  • 拓扑结构总是会发生变化,这是设计使然。
  • 网络和您的系统是异构的。不同的系统在负载下表现不同。
  • 当您最不期望的时候,您的虚拟机会在最不合适的时间消失。
  • 因为人们可以使用键盘和鼠标,所以会发生错误。
  • 您的客户可以在(并且会)在< 500 毫秒内采取下一步行动。

通常,测试环境提供完美的世界条件,这避免了违反这些假设。没有考虑(和测试)这些现实世界属性的系统是为一个永远不会发生坏事的世界而设计的。因此,当系统开始违反隐藏的假设时,您的系统将表现出不可预见且看似非确定性的行为。这转化为客户的糟糕性能,以及极其困难的故障排除过程。

没有计划潜在流量

估计未来的流量量很困难,我们发现我们出错的次数比我们正确的次数更多。高估流量意味着组织正在浪费精力为不存在的现实而设计。低估流量可能更灾难性。各种原因会导致意外的高流量负载,社交媒体营销活动意外走红就是一个很好的例子。突然,您的系统无法管理传入的流量,组件开始崩溃,一切陷入停滞。

作为一家初创企业,您始终在寻找吸引新客户并获得更多市场份额的方法。这如何以及何时实现是难以预测的。在互联网的规模上,任何事情都可能发生,您应该假设它会发生。

通过客户通知提醒

当客户对您的产品投入并相信问题是可以解决的时,他们可能会尝试联系您的支持人员寻求帮助。这可能是通过电子邮件、打电话或打开支持票。服务故障会导致呼叫量或电子邮件流量激增。您的销售人员甚至可能转达这些消息,因为(潜在)客户也告诉他们。如果服务中断影响到战略客户,您的 CEO 可能会直接告诉您(这在早期可能是可以的,但绝对不是您想长期处于的状态)。

客户沟通并不总是清晰直白,而是基于客户的独特体验。如果客户成功人员没有意识到这些是弹性问题迹象,他们将照常进行业务,您的工程人员将不会收到反馈。当它们没有被正确识别和管理时,通知可能会变成非语言。例如,您可能会突然发现客户取消订阅的比率有所上升。

在与少量客户群合作时,通过客户了解问题是“大部分”可控的,因为他们相当宽容(毕竟他们与您一起经历了这段旅程)。但是,随着客户群的增长,通知将开始堆积,达到无法管理的状态。

图 1:在客户通知管理不善的组织中看到的沟通模式。

如何摆脱瓶颈?

一旦出现故障,您希望尽快恢复并详细了解故障原因,以便改进系统并确保不再发生。

在瓶颈中解决产品和服务的弹性可能很困难。战术解决方案通常意味着您最终陷入一场又一场的火灾。但是,如果在瓶颈中进行战略性管理,您不仅可以减轻团队的压力,还可以从过去的恢复工作中吸取教训,帮助您在超高速增长阶段及以后进行管理。

以下五个部分实际上是您的组织可以实施的策略。我们认为它们按顺序排列,应该作为一个整体来考虑。但是,根据您组织的成熟度,您可能决定利用一部分策略。在每个策略中,我们都列出了几个有助于实现该策略的解决方案。

确保已实施基本弹性技术

有一些基本的技巧,从架构到组织,可以提高您的弹性。它们将您的产品保持在正确的位置,使您的组织能够有效地扩展。

在一个区域内使用多个区域

对于高度关键的服务(及其数据),请配置并启用它们在多个区域中运行。这应该会提高您的系统可用性,并在发生中断(在一个区域内)时提高您的弹性。

指定适当的计算实例类型和规格

业务关键服务应适当地分配计算能力。如果服务需要全天候运行,您的基础设施应反映这些要求。

将投资与关键服务层级相匹配

许多组织通过识别关键服务层级来管理投资,并了解并非所有业务系统在提供客户体验和支持收入方面都具有同等重要性。识别服务层级和与之相关的弹性结果(由服务级别协议 (SLA) 告知),以及支持这些结果的架构和设计模式,为您的产品开发团队提供了有用的护栏和治理。

在整个系统中明确定义所有者

系统中存在的每个服务都应具有明确定义的所有者。此信息可用于帮助将问题引导到正确的地方,以及引导到能够有效解决问题的人员。实施一个开发者门户,该门户提供一个软件服务目录,其中明确定义了团队所有权,这有助于内部沟通模式。

自动化手动弹性流程(在时间框内)

某些通过人工解决的弹性问题可以自动化:例如重启服务、添加新实例或恢复数据库备份等操作。许多操作很容易自动化,或者只需在您的云服务提供商中进行配置更改即可。在瓶颈中,实施这些功能可以为团队提供所需的缓解,提供急需的喘息空间和时间来解决根本原因。

确保将这些实现保持在最简单和时间限制内(最多几天)。请记住,这些最初是创可贴,自动化它们只是另一种(尽管更好)类型的创可贴。将这些集成到您的监控解决方案中,使您能够了解系统自动恢复的频率以及所需的时间。同时,这些指标使您能够优先考虑摆脱对这些创可贴解决方案的依赖,并使整个系统更加健壮。

通过可观察性和监控提高平均恢复时间

要摆脱瓶颈,您需要了解当前状态,以便您可以对投资方向做出有效的决策。如果您想达到 5 个 9,但不知道目前实际提供了多少个 9,那么您甚至很难知道应该走哪条路。

要了解自己的位置,您需要投资可观察性。可观察性使您能够在弹性变得无法管理之前,更积极地进行弹性投资。

集中您的日志,以便通过单个界面查看

聚合来自核心服务和系统的日志,以便通过中央界面访问。这将使它们易于被多个人访问,并减少故障排除工作量(可能缩短平均恢复时间)。

为日志消息定义清晰的结构化格式

任何曾经解析过聚合日志消息的人都会告诉你,当多个服务遵循不同的日志结构时,要找到任何东西都是一件令人难以置信的混乱的事情。每个服务最终都使用自己的语言,只有最初的作者才能理解日志。理想情况下,一旦这些日志被聚合,从开发人员到支持团队的任何人都应该能够理解日志,无论其来源如何。

使用组织范围的标准化格式来构建日志消息。大多数日志记录工具都支持 JSON 格式作为标准,这使得日志消息结构可以包含元数据,例如时间戳、严重性、服务和/或相关 ID。借助日志管理服务(通过可观察性平台),人们可以跨这些属性进行过滤和搜索,以帮助调试瓶颈问题。为了提高搜索效率,建议使用较少的日志消息,其中包含更多包含相关信息的字段,而不是使用许多包含少量字段的消息。实际消息本身可能仍然特定于特定服务,但与日志消息关联的属性对每个人都有帮助。

将您的日志消息视为一项关键信息,不仅对编写它们的开发人员可见。您的支持团队在调试初始客户查询时可以变得更加有效,因为他们可以理解他们正在查看的结构。如果每个服务都能使用相同的语言,提供支持和调试帮助的障碍就会消除。

添加靠近客户体验的可观察性

凡是能被衡量的,就能被管理。

-- 彼得·德鲁克

虽然基础设施指标和服务消息日志很有用,但它们级别较低,无法提供实际客户体验的任何上下文。另一方面,客户通知是问题的直接指示,但它们通常是轶事性的,在模式方面没有提供太多信息(除非您投入工作来找到一个)。

监控核心业务指标使团队能够观察客户的体验。它们通常通过产品的需求和功能来定义,提供围绕许多客户体验的高级上下文。这些指标包括已完成的交易、视频的启动和停止速率、API 使用情况或响应时间指标。隐式指标在衡量客户体验方面也很有用,例如前端加载时间或搜索响应时间。将观察到的内容直接与客户体验您的产品的方式相匹配至关重要。同样重要的是要注意,与客户体验一致的指标在 B2B 环境中变得更加重要,因为在仅测量系统各个组件时,您可能没有足够的 数据点来了解客户问题。

在一个客户那里,服务开始发布与产品体验相关的域事件:例如添加到购物车、无法添加到购物车、交易完成、付款已批准等事件。然后,这些事件可以被可观察性平台(如 Splunk、ELK 或 Datadog)捕获并显示在仪表板上,并进行进一步分类和分析。可以捕获和分类错误,从而更好地解决与意外客户体验相关的错误。

图 2:专注于用户体验的仪表板示例

通过核心业务指标收集的数据可以帮助您了解哪些可能出现故障,以及系统的阈值在哪里以及它在超出阈值时如何管理。这提供了更多关于如何克服瓶颈的见解。

使用状态指示器向客户提供产品状态信息

管理来自客户的不同问题的传入查询可能很困难,支持服务很快就会发现他们正在扑灭一场又一场的火灾。管理问题数量对于初创公司的成功至关重要,但在瓶颈中,您需要寻找系统性的方法来减少这种流量。将呼叫流量从支持部门转移出去的能力将提供一些喘息空间,并有更大的机会解决正确的问题。

服务状态指示器可以向客户提供他们正在寻找的信息,而无需联系支持部门。这可以通过公共仪表板、电子邮件或甚至推文的形式实现。它们可以利用后端服务运行状况和就绪性检查,或指标组合来确定服务可用性、降级和中断。在事件发生期间,状态指示器可以提供一种方法,一次性向许多客户更新产品的状态。

与客户建立信任与创建可靠且弹性的服务一样重要。为客户提供了解服务状态和预期解决时间表的方法有助于通过透明度建立信心,同时也为支持人员提供了解决问题的空间。

图 3:在主动管理客户通知方式的组织内的沟通模式。

转向明确的弹性业务需求

作为一家初创公司,新功能通常被认为比技术债务更有价值,包括与弹性相关的任何工作。正如之前所说,这在最初是有道理的。新功能和增强功能有助于留住客户并吸引新客户。提供新功能的工作理论上应该会导致收入增加。

随着组织的增长并发现新的挑战来增加收入,这并不一定成立。弹性故障是这些挑战的来源之一。要克服这一点,需要改变您对产品弹性的价值观。

了解服务故障的成本

对于初创公司来说,未能达到本季度收入目标的后果可能与规模化公司或成熟产品不同。但正如经常发生的那样,最初的“新功能比技术债务更有价值”的决定会成为组织文化的永久特征——无论实际的收入影响是否可以证明,甚至是否计算出来。从初创公司转向规模化公司所需的成熟度的一个方面在于决策的以数据为导向的元素。组织是否在跟踪每个发布的新功能的价值?组织是否将运营投资视为对新收入的贡献,而不仅仅是成本中心?停机或反复停机的成本是否已知,包括浪费的内部劳动时间和损失的收入?作为一家初创公司,在大多数情况下,你没有什么损失。但随着你的成长,情况就不一样了。

因此,将服务故障的成本纳入整体产品管理和收入确认价值流的分析至关重要。了解你的收入“速度”将提供一种简单的方法来量化每分钟停机的直接成本。跟踪团队中每个人在停机事件中所花费的成本,从客户支持电话到开发人员、管理人员、公共关系/营销人员,甚至销售人员,这将是一次令人大开眼界的体验。再加上处理停机事件的机会成本,而不是扩大客户覆盖范围或交付新功能,停机事件在弹性方面的真实范围和影响就会变得显而易见。

将弹性作为一项功能进行管理

开始将弹性视为不仅仅是技术期望。它是一项核心功能,客户会期望得到它。由于他们期望得到它,因此它应该成为除其他功能之外的首要考虑因素。这种演变的一部分是关于责任所在的变化。它不再仅仅是技术部门的责任,而是产品和业务的责任。组织中的多个层级需要将弹性视为优先事项。这表明弹性获得了与任何其他功能相同的关注度。

产品和技术之间的密切合作对于确保你能够在故事定义、实施和与组织其他部门的沟通中设定正确的期望至关重要。弹性虽然是一项核心功能,但对客户来说仍然是不可见的(不像 UI 或 API 的新增功能)。这两个部门需要协作,以确保弹性得到适当的优先级排序并有效地实施。

这里的目标是将弹性从反应性问题转变为主动性问题。如果你的团队能够主动,你也可以在你的业务发生重大事件时做出更适当的反应。

需求应反映现实的期望

了解相对于需求和客户期望的弹性的现实期望是保持工程工作成本效益的关键。不同级别的弹性,以正常运行时间和可用性衡量,具有截然不同的成本。 “三九”和“四九”可用性(99.9% 对 99.99%)之间的成本差异可能是 10 倍。

了解你对每个业务能力的客户需求非常重要。你和你的客户是否期望 24x7x365 的体验?你的客户在哪里?他们是否位于特定地区,还是全球分布?他们主要通过移动设备使用你的服务,还是通过你的公共 API 集成?例如,在通过移动设备交付的服务上提供 99.999% 的正常运行时间是一种无效的资本使用方式,因为移动设备由于手机可靠性限制,只能享受 99.9% 的正常运行时间。

在考虑弹性时,这些都是需要问的重要问题,因为你不想为实现没有感知到的客户价值的弹性级别付费。它们还有助于设定和管理对正在构建的产品、构建和维护它的团队、组织中销售它的团队以及使用它的客户的期望。

首先找出你的问题,避免过度工程

如果你正在手动解决弹性问题,你的第一直觉可能是将其自动化。为什么不呢?虽然它可以提供帮助,但它在实施时间限制在非常短的时间内(最多几天)时最有效。花费更多时间可能会导致在实际上只是一个症状的领域过度工程。大量的時間、精力和金钱将投入到一个仅仅是另一个创可贴的东西上,而且很可能不可持续,或者更糟糕的是,会导致它自己的一系列二阶挑战。

与其直接转向战术解决方案,不如抓住这个机会真正找出你的问题:故障线在哪里,你的可观察性试图告诉你什么,以及哪些设计选择与这些故障相关。你可能可以通过压力、混乱或探索性测试来发现这些故障线。利用这个机会来发现其他系统压力点,并确定在哪里可以获得最大的投资价值。

随着你的业务发展和扩展,重新评估过去的决定至关重要。在初创阶段有意义的东西可能无法帮助你度过超高速增长阶段。

在收集需求时利用多种技术

收集面向技术的功能需求可能很困难。不熟悉弹性术语的产品经理或业务分析师可能难以理解。这通常会转化为模糊的需求,例如“使 x 服务更具弹性”或“100% 的正常运行时间是我们的目标”。你定义的需求与最终的实现一样重要。有很多技术可以帮助我们收集这些需求。

在编写需求之前尝试进行事后分析。在这个轻量级活动中,不同角色的个人会给出他们对他们认为可能失败或正在失败的内容的看法。事后分析提供了宝贵的见解,了解人们如何看待潜在的故障原因以及相关的成本。随后的讨论有助于优先考虑需要变得有弹性的东西,在任何故障发生之前。至少,你可以创建新的测试场景来进一步验证系统弹性。

另一个选择是与技术负责人和架构 SME 一起编写需求。创建有效的弹性系统的责任现在由团队中的领导者共同承担,每个人都可以谈论设计的不同方面。

这两种技术表明,收集弹性功能的需求不是单一的责任。它应该在团队中的不同角色之间共享。在尝试的每项技术中,请记住谁应该参与以及他们带来的观点。

发展您的架构和基础设施以满足弹性需求

对于初创公司来说,架构的设计取决于你进入市场的速度。这通常意味着最初有效的架构可能会成为你向规模化公司过渡的瓶颈。你的产品的弹性最终将取决于你做出的技术选择。这可能意味着检查系统的整体设计和架构,并对其进行演变以满足产品弹性需求。我们之前提到的很多内容都可以帮助你获得数据点和瓶颈内的松弛。在这个空间内,你可以演变架构并整合能够实现真正弹性产品的模式。

广泛地查看你的架构并确定适当的权衡

无论是在隐式还是显式的情况下,在创建初始架构时,都做出了权衡。在初创公司的实验和获得牵引力的阶段,高度关注快速将产品推向市场,保持开发成本低廉,以及能够轻松地修改或调整产品方向。权衡是牺牲了理想架构带来的弹性优势。

以由函数即服务 (FaaS) 支持的 API 为例。这种方法是创建无需管理其运行的基础设施的东西的好方法,它可能满足我们关注领域的三个目标。另一方面,它受到其允许运行的基础设施、服务的时序约束以及许多不同函数之间潜在的通信复杂性的限制。虽然不是不可实现,但架构的约束可能会使实现产品所需的弹性变得困难或复杂。

随着产品和组织的增长和成熟,其约束也会发生变化。重要的是要承认,早期的设计决策可能不再适合当前的操作环境,因此需要引入新的架构和技术。如果未解决,早期做出的权衡只会放大超高速增长阶段的瓶颈。

通过有效的错误恢复策略增强弹性

从监控器收集的数据可以显示高故障率来自哪里,无论是第三方集成、备份队列、回退还是其他。这些数据可以推动关于要实施哪些适当的恢复策略的决策。

在适当的情况下使用缓存

在检索信息时,缓存策略可以从两个方面提供帮助。首先,它们可以用于通过为相同的查询提供缓存的结果来减少对服务的负载。缓存也可以用作后端服务无法成功返回时的回退响应。

权衡是可能向客户提供陈旧的数据,因此请确保你的用例对陈旧的数据不敏感。例如,你不会希望将缓存的结果用于实时股票价格查询。

在适当的情况下使用默认响应

作为缓存的替代方案,缓存提供查询的最后已知响应,可以提供静态默认值,当后端服务无法成功返回时。例如,如果宁愿冒失去销售的风险,也不愿冒在交易中亏钱的风险,那么提供零售价格作为价格折扣服务的回退响应将不会造成任何伤害。

对变异请求使用重试策略

当客户端调用服务以影响数据更改时,用例可能需要在继续之前成功请求。在这种情况下,重试调用可能是合适的,以最大程度地减少需要使用错误管理流程的频率。

有一些重要的权衡需要考虑。没有延迟的重试可能会导致请求风暴,这会导致整个系统在负载下崩溃。使用指数级回退延迟可以减轻流量负载的风险,但会占用连接套接字等待长时间运行的请求,这会导致一组不同的故障。

使用幂等性简化错误恢复

实现任何类型重试策略的客户端可能会生成多个相同的请求。确保服务可以处理多个相同的变异请求,并且还可以处理从故障点恢复多步骤工作流。

设计适合业务的故障模式

在系统中,故障是必然的,你的目标是尽可能地保护最终用户体验。特别是在由下游服务支持的情况下,你可能能够预测故障(通过可观察性)并提供替代流程。利用这些集成的底层服务可以设计为具有适合业务的故障模式。

考虑一个由微服务架构支持的电子商务系统。如果支持订单功能的下游服务不堪重负,最好暂时禁用订单按钮,并向客户显示有限的错误消息。虽然这为用户提供了清晰的反馈,但关注销售转化率的产品经理可能会选择捕获订单,并提醒客户订单确认延迟。

故障模式应该嵌入到上游系统中,以确保业务连续性和客户满意度。根据您的架构,这可能涉及您的 CDN 或 API 网关在请求过载您的子系统时返回缓存的响应。或者,如上所述,您的系统可能为特定故障模式提供通往最终一致性的替代路径。这比显示通用错误页面(表示“出现错误”)更有效,也更以客户为中心。

解决单点故障

单个服务可以轻松地从管理产品的单一职责扩展到多个职责。对于初创公司来说,追加到现有服务通常是最简单的方法,因为基础设施和部署路径已经解决。然而,服务很容易膨胀并变成一个整体,从而创建一个故障点,可能导致产品的大部分或全部部分崩溃。在这种情况下,您需要了解如何拆分架构,同时保持产品的整体功能。

在一家金融科技客户公司,在快速增长期间,其单体系统的负载会大幅波动。由于单体性质,所有功能同时崩溃,导致收入损失和客户不满。长期的解决方案是将单体系统拆分成几个可以水平扩展的独立服务。此外,他们引入了事件队列,因此事务永远不会丢失。

实施微服务方法并非一项简单直接的任务,需要时间和精力。首先定义一个需要提高弹性的领域,然后逐个提取其功能。推出新服务,根据需要调整基础设施配置(增加预配容量,实施自动扩展等)并监控它。确保用户旅程没有受到影响,并且整体弹性有所提高。一旦稳定性得到保证,继续迭代该领域中的每个功能。如客户示例中所述,这也是引入有助于提高系统整体弹性的架构元素的机会。事件队列、断路器、舱壁和反腐败层都是有助于提高系统整体可靠性的有用架构组件。

持续优化您的弹性

渡过瓶颈是一回事,避免瓶颈又是另一回事。随着您的发展,您的系统弹性将不断受到考验。新功能会导致系统负载增加的新途径。架构更改会引入未知的系统稳定性。您的组织需要领先于最终会发生的事情。随着您的组织成熟和发展,您对弹性的投资也应该随之增加。

定期进行混沌测试以验证系统弹性

混沌工程是真正弹性产品的基石。其核心价值在于能够以您可能从未想到的方式产生故障。当这种混乱正在制造故障时,同时运行用户场景有助于了解用户体验。这可以增强您对系统能够承受意外混乱的信心。同时,它可以识别哪些用户体验受到系统故障的影响,从而为下一步改进提供背景信息。

虽然您可能更愿意针对开发或 QA 环境进行测试,但混沌测试的价值来自生产或类似生产的环境。目标是了解系统在混乱面前的弹性。早期环境(通常)没有配备生产环境中相同的配置,因此不会提供所需的信心。在生产环境中运行这样的测试可能令人生畏,因此请确保您有信心恢复服务。这意味着整个系统可以重新启动,数据可以恢复(如果需要),所有这些都可以通过自动化完成。

从可以提供有用数据的简单易懂的场景开始。随着您积累经验和信心,考虑使用您的负载/性能测试来模拟用户,同时执行您的混沌测试。确保团队和利益相关者知道即将运行实验,以便他们做好监控准备(以防出现问题)。像 Litmus 或 Gremlin 这样的框架可以为混沌工程提供结构。随着您对弹性的信心和成熟度不断提高,您可以开始运行团队事先没有收到通知的实验。

招募具有大规模弹性知识的专家

在构建和交付初始产品时聘用通才是有意义的。时间和金钱非常宝贵,因此拥有通才可以提供灵活性,确保您能够快速进入市场,并且不会消耗掉初始投资。但是,团队承担了超出其能力范围的工作,并且随着您的产品规模扩大,曾经足够好的东西不再适用。一个勉强进入市场的略有不稳定的系统,随着您的规模扩大,会变得更加不稳定,因为管理它所需的技能已经超过了现有团队的技能。与技术债务一样,这可能是一个滑坡,如果不加以解决,问题将继续加剧。

为了维持产品的弹性,您需要招募具有这方面专业知识的人员来专注于该能力。专家会带来对现有系统的全新视角,以及他们识别差距和改进领域的能力。他们过去的经验可以对团队产生双重影响,在急需的领域提供急需的指导,并进一步投资于员工的成长。

始终保持或提高您的可靠性

在 2021 年,DevOps 状态报告将第五个关键指标从可用性扩展到可靠性。在运营性能方面,它断言产品能够保持其承诺。弹性与之直接相关,因为它是一种关键的业务能力,可以确保您的可靠性。随着许多组织更频繁地推向生产,需要确保可靠性保持不变或得到改善。

在您的可观察性和监控到位后,确保它告诉您的内容与您的服务级别目标 (SLO) 中所述的内容相符。每次部署到生产环境时,监控器都不应偏离您的 SLA 保证的内容。某些部署结构(如蓝绿或金丝雀(在某种程度上))可以帮助在向广大受众发布之前验证更改。在生产环境中有效地运行测试可以增强您对协议没有改变并且弹性保持不变或得到改善的信心。

随着组织的增长,弹性和可观察性

阶段 1

实验

原型解决方案,高度关注快速将产品推向市场

阶段 2

获得牵引力

弹性和可观察性是通过开发人员干预手动实施的

解决弹性的优先级主要来自技术债务

仪表板反映了低级服务统计信息,例如 CPU 和 RAM

大多数支持问题来自客户的电话或短信

阶段 3

(超)增长

弹性是交付给客户的核心功能,其优先级与功能相同

可观察性能够反映整体客户体验,通过仪表板和监控反映出来

重新架构或重新创建有问题的服务,在此过程中提高弹性

阶段 4

优化

平台从面向内部的服务演变而来,将可观察性和计算环境产品化

定期进行混沌工程练习,几乎没有通知

为团队补充精通大规模弹性的工程师

总结

作为一个规模化企业,您有效地驾驭(超)增长阶段的能力在一定程度上取决于产品的弹性。高增长率开始给在初创阶段开发的系统带来压力,未能解决该系统的弹性问题通常会导致瓶颈。

为了最大程度地降低风险,弹性需要被视为一等公民。具体细节可能因您的环境而异,但在较高层面上,以下考虑因素可以有效:

  • 弹性是您产品的一项关键功能。它不再仅仅是一个技术细节,而是客户会期望的关键组成部分,它将公司转向积极主动的方法。
  • 构建客户状态指标以帮助转移一些支持请求,让您的团队有喘息的机会来解决重要问题。
  • 客户体验应该反映在您的可观察性堆栈中。监控反映客户体验的核心业务指标。
  • 了解您的仪表板和监控器告诉您的内容,以了解哪些是最需要解决的关键领域。
  • 随着您识别出特定挑战,演变您的架构以满足您的弹性目标。初始设计可能在小规模情况下有效,但在您过渡到规模化企业时会变得越来越有限。
  • 在设计故障模式时,寻找对消费者友好的故障方式,帮助确保连续性和客户满意度。
  • 为您的产品定义现实的弹性期望,并了解为其提供服务的限制。利用这些知识为您的客户提供有效的 SLA 和合理的 SLO。
  • 在您渡过瓶颈后优化您的弹性。将混沌工程纳入定期实践或招募专家。

成功地将这些实践纳入其中,将导致一个未来组织,在该组织中,弹性被构建到业务目标中,涵盖人员、流程和技术的各个方面。


致谢

本文在很大程度上得益于我们许多同事的思想、想法和反馈。感谢 Martin Fowler、Rickey Zachary、Vanessa Towers、Brandon Byars、Nic Cheneweth、Matthew Foster、Dale Peakall、Melissa Newman、Premanand Chandrasekaran、Karthik Krishnan、Kamil Markow Stefania Stefansdottir 和 Matt Newman。

特别感谢 Tim Cochran 在我们撰写本文的整个过程中提供的指导。

特别感谢 Ranbir Chawla 对早期草稿的贡献。

重大修订

2023 年 8 月 22 日:发布(完整版)