韧性设计

Chinese, Simplified
本文地址
https://architect.pub/resilience-design
SEO Title
resilience design

【架构质量】可靠性系列#1:可靠性与韧性

Chinese, Simplified

每当我与客户和合作伙伴谈论可靠性时,我都会被提醒,虽然组织和客户之间的目标和优先级不同,但归根结底,每个人都希望他们的服务能够发挥作用。作为客户,您希望能够在方便的时候在线进行操作。作为一个组织或服务提供商,您希望您的客户在他们想要的任何时候执行他们想要执行的任务。

本文是关于构建弹性服务的四部分系列中的第一篇。在我的前两篇文章中,我将讨论与业务战略相关的主题,然后我们将更深入地研究技术细节。四个帖子的完整系列将涵盖:

  • 1. 可靠性与弹性——可靠性和弹性之间有什么区别,为什么重要?
  • 2. 与可靠性相关的常见威胁——DIAL(发现、错误、授权/身份验证、限制/延迟)是一种方便的助记符,可帮助团队以结构化的方式集思广益,以解决其服务组件之间交互的潜在故障。关于故障模式和故障点的头脑风暴是弹性建模和分析 (RMA) 的关键阶段,可以帮助团队提高服务的可靠性。
  • 3. 可靠性增强技术——以 DIAL 中的“D”和“A”为例,我们将研究一些可以纳入与发现和身份验证相关的设计中的可靠性增强技术。
  • 4. 可靠性增强技术——以 DIAL 中的“I”和“L”为例,我们将研究一些可用于与错误和限制相关的设计中的可靠性增强技术。

我的目的是深入了解 Microsoft 如何看待可靠性以及我们为提高客户服务可靠性而采用的流程和技术。

那么什么是可靠性?当我询问客户和合作伙伴时,最常见的回答是性能、速度、可用性的一致性——也许最重要的是——弹性。我们都同意的一件事是,要使系统或服务可靠,用户必须相信“它可以正常工作”。

电气和电子工程师协会 (IEEE) 可靠性协会指出,可靠性 [工程] 是“一门设计工程学科,它应用科学知识来确保系统在给定的环境中在所需的时间内执行其预期功能,包括能够在整个生命周期内测试和支持系统。”对于软件,它将可靠性定义为“在特定环境中特定时间段内软件无故障运行的概率”。

可靠的云服务本质上是按照设计者的预期、预期的时间以及客户连接的任何位置运行的服务。这并不是说每个组件都必须在 100% 的时间内完美运行。最后一点让我们明白了我认为可靠性和弹性之间的区别。

可靠性是云服务提供商追求的结果——它就是结果。弹性是基于云的服务能够承受某些类型的故障,但从客户的角度来看仍保持正常运行的能力。换句话说,可靠性是结果,而弹性是实现结果的方式。一项服务可以被描述为可靠,仅仅因为该服务的任何部分都没有发生过故障,但该服务不能被视为具有弹性,因为这些增强可靠性的能力可能从未经过测试。

这里的关键要点是在软件开发生命周期的每个阶段关注弹性以及在您的服务中设计和构建弹性的重要性。 要了解有关构建可靠在线服务的基础知识的更多信息,请阅读我们的白皮书“设计可靠云服务的介绍”。

原文:https://www.microsoft.com/security/blog/2014/03/24/reliability-series-1…

本文:https://jiagoushi.pro/reliability-series-1-reliability-vs-resilience

SEO Title
Reliability Series #1: Reliability vs. resilience

【韧性工程】所有开发人员都应该知道的韧性软件策略

Chinese, Simplified

失败是不可避免的。 然而,正确的软件设计和开发选择可以帮助最大限度地减少其影响、隔离问题并加快恢复时间。

 

许多架构师努力设计具有避免灾难性故障的能力的应用程序系统。不幸的是,在现实世界中,导致崩溃的错误和过载是不可避免的。


为了正确处理此类故障,开发团队必须为自己配备正确的软件弹性实践。在追求设计风格(例如基于微服务的架构)时,这一点尤为重要,在这种架构中,故障可能会蔓延到分布式组件并导致广泛的中断。

各种软件弹性技术和机制可以帮助团队响应错误、启动恢复过程并在发生故障时保持一致的应用程序性能。让我们来看看架构师可以实施的四种策略来解决错误、最大限度地减少故障的影响并持续维护弹性软件架构。

创建死信队列


个人通信可能因多种原因而陷入困境,例如不可用的收件人、格式不正确的请求和数据丢失。这在事件驱动架构中尤其成问题,其中请求通常被放入消息队列以等待处理,而请求服务继续进行下一个操作。因此,未处理的消息会迅速堵塞这些队列。

死信队列引入了一种机制,专注于处理这些流浪消息,以防止它们使通信渠道混乱,并不必要地吸走保持它们流通所需的资源。开发团队可以设置死信队列来识别滞留消息并隔离故障。这使架构师能够检查特定错误,并维护有助于指导未来设计选择的详细历史文档。

一旦这些恶意消息被认为是过时的,就可以随意从队列中删除它们。或者,可以将它们重新提交以恢复操作或复制错误以进行调试。

使用功能切换进行修改


软件弹性的另一个重要因素与开发团队的功能更新发布周期的方法有关。与其停止添加功能和修改应用程序功能的操作,组织可以使用功能切换方法在推出和更新期间保持应用程序正常运行。

功能切换使开发人员能够增量修改应用程序,同时保持现有生产级代码不变。金丝雀发布和 A/B 测试等技术使开发人员能够在有限数量的实例中推出更新的代码,同时将原始代码保留在生产环境中。

使用功能切换方法,团队可以通过监视新版本实例并使用类似切换机制的回滚来战略性地配置版本,以防修改导致损坏。在某些情况下,如果系统检测到某些错误或性能不一致,团队可能能够自动触发这些回滚切换。

 

基本弹性设计模式


为了维护弹性软件,开发团队使用特定的设计模式,专注于包含故障和提供紧急对策。许多模式提供了这些类型的恢复机制,并阻止错误从一个分布式组件不受控制地传播到另一个分布式组件。这里有些例子:

  • 舱壁(Bulkhead)。此模式隔离子系统并配置单个模块以在出现故障时停止与其他组件的通信,从而降低问题传播的风险。
  • 背压(Backpressure)。背压模式自动推回超过预设流量吞吐量容量限制的工作负载请求,保护敏感系统免受过载。
  • 断路器(Circuit breaker)。基于隔板和背压模式,断路器提供了一种机制,可以自动切断与有问题的组件的连接。它将定期重试连接以查看错误是否已解决。
  • 批量到流(Batch-to-stream.)。该模式旨在管理批处理吞吐量,修改批处理工作负载并将其转换为简化的 OLTP 事务。
  • 优雅的退化(Graceful degradation)。这种设计模式本质上为应用程序的所有主要组件安装了一个回退机制。虽然这主要是为了帮助为更新提供回滚,但它也可以在突然失败的情况下派上用场。

 

促进组件之间的松散耦合


传统的单体应用程序意味着紧密耦合架构中的刚性依赖关系。结果,一个软件组件几乎肯定会影响另一个。或者,在微服务等分布式系统中,架构师可以通过解耦软件组件来最小化这些依赖关系。

在松散耦合架构中,应用程序组件、模块和服务之间存在的依赖关系保持在最低限度。相反,抽象处理必要的数据传输和消息传递过程。因此,发生在一个组件上的更新或故障不太可能导致对另一个组件的意外更改。解耦可以隔离问题并防止它们在其他软件环境中传播,从而限制出现广泛错误的风险。

使用 sidecar 容器来限制故障


Sidecar 是一个支持容器,它与主应用程序容器在同一个 pod 中运行。 Sidecar 使团队能够向容器添加功能并与外部服务集成,而无需更改主要的现有应用程序容器实例。

对于软件弹性,这种技术是有益的,因为主要的应用程序逻辑和代码库保持隔离,限制了风险和故障。然而,边车也有缺点。例如,添加 sidecar 意味着开发人员负责管理更多的容器和增加的资源消耗。努力确保sidecars 不会使工作负载复杂到影响应用程序性能的程度。对于初学者,您需要建立一个完整的容器监控系统,该系统将跟踪边车并衡量它们对它们所服务的生产级容器的影响。

原文:https://www.techtarget.com/searchapparchitecture/feature/Resilient-soft…

本文:https://jiagoushi.pro/node/2150

SEO Title
Resilient software strategies all developers should know

【韧性架构】韧性性工程的重要性

Chinese, Simplified

Antique staircase (seen in Vienna, Austria)

韧性工程的重要性


本周 AWS 发生了更大的中断,当然媒体报道再次大肆报道。例如,“亚马逊网络服务中断使企业陷入困境”,华盛顿邮报的标题,仅举一个例子。

你可以找到更多的媒体报道。然而,对我来说,有趣的部分并不是 AWS 发生了罕见的中断之一。这是大多数文章的底线:AWS 发生了部分中断,因此使用 AWS 的公司步履蹒跚。

换句话说:AWS 是有罪的。这些公司是受害者。

个人觉得,没那么简单。实际上,我认为 AWS 按承诺交付,并且确信像 Netflix 这样的一些公司根本不会因为这次中断而步履蹒跚。那么,其他公司做错了什么?

不了解分布式系统


IMO 的第一个问题是,步履蹒跚的公司对分布式系统的本质了解得不够好,无法正确评估风险。

有趣的是,我刚刚在上一篇文章中描述了分布式系统的影响:

  • 跨流程边界出现问题。
  • 你无法预测什么时候会出错。
  • 它会在应用程序级别打击你。

这就是您对分布式系统的基本总结。或者正如亚马逊首席技术官 Werner Vogels 有时描述的那样:

“一切都失败了,一直都是。” ——维尔纳·沃格尔斯

他之所以这么说,是因为 AWS 的人会做的很马虎。看看他们运营的系统环境的复杂性和规模以及他们经历的罕见的更大中断,他们做得非常好 . 他这么说是因为他真正了解分布式系统的本质。

这种“事情会出错并在应用程序级别打击你”不仅对应用程序的某些部分有效。您还需要考虑您使用的基础设施。在任何分布式系统中,即不同的进程(通常在不同的机器上运行)交互时,您必须查看所有“移动”部分及其交互。

您使用的基础架构也是分布式应用程序环境的一部分。这是陷入困境的公司没有(足够)考虑到的。

100% 可用性陷阱


如果软件工程师设计一个分布式应用程序,例如,使用微服务,至少有时他们会考虑他们自己实现的应用程序部分的潜在故障

但是,一旦涉及应用程序与之交互的其他部分,无论是其他应用程序还是基础设施组件,100% 可用性陷阱就会发生。这个陷阱是一种普遍的、隐含的思维模式,在企业环境中尤其常见。陷阱是这样的:

100% 可用性陷阱(谬误)

我的应用程序与之交互的所有东西都是 100% 可用的。

如果您明确询问人们是否认为这些其他部分可能会失败,他们会说是的。但他们的决定和设计并没有以任何方式反映它。 

想想你知道的应用程序代码,例如,尝试写入数据库。如果访问失败会怎样?是否有替代操作编码在这种情况下要做什么,例如,首先重试写入,如果仍然失败将写入请求放入队列并稍后处理,包括监视和处理队列的逻辑?

我很确定,没有这样的代码。最有可能的是,相应的异常被捕获、记录,然后……好吧,继续前进,就好像什么都没发生一样。在韧性工程中,这被称为“静默失败”。您检测到错误,决定忽略它并继续前进。

这种行为在某些地方可能很好,但通常情况并非如此。大多数情况下,这只是 100% 可用性陷阱的结果:从未讨论过故障场景,期望的行为仍未定义,因此实现开发人员不知道如何处理这种情况。因此,他们记录了出现问题并继续前进。他们还应该做什么?

不过,从业务角度来看,这通常不是您想要的。假设这是关于写命令。订单就是你赚钱的东西。订单就是你赖以生存的东西。因此,这是整个应用程序中最重要的一次写入。

现在假设如果由于某种原因写入失败,则命令只是默默地不写入。如果你搜索它,你可以在日志中找到它,但就是这样。这不是你想要的。

或者客户收到一条通用消息,例如:“处理您的请求时出现问题。请稍后再试。” – 这有点好,但也不是你想要的。

从业务的角度来看,您想要的根本不是失去任何订单,因为订单是您存在的基础。

因此,您会期望一些逻辑,例如首先重试写入。如果失败,将订单缓存在队列或其他辅助存储介质中,向客户发送消息,例如“非常感谢您的订单。由于暂时的技术问题,我们无法立即处理您的订单。但我们会在问题解决后尽快处理。这是一个 URL,您可以在其中跟踪您的订单处理状态”,实现并运行队列处理器以及订单处理状态页面。

如果您从业务角度对订单写入过程的期望行为进行推理,您可能会得到这样的结果。但由于 100% 可用性陷阱,通常不会进行这种讨论。 

因 AWS 中断而步履蹒跚的公司很可能从未进行过这样的讨论。

不评估 SLA


但是,即使公司对分布式系统了解得不够好并陷入 100% 可用性陷阱,仍然存在 AWS 提供的 SLA,应将其视为风险管理来源。

阅读 AWS 提供的 SLA,我的第一个想法是,如果我想将停机风险降到最低,我需要自己采取额外的措施。我的印象是,步履蹒跚的公司没有这样的想法。

事件的事后分析表明,Kinesis 处于停电的中心。这也影响了其他一些使用 Kinesis 的 AWS 服务。

通常,像 AWS 这样的公司会尽量减少级联故障的可能性。但是在像 AWS 这样的复杂系统环境中,您往往会有微妙的、未知的交叉依赖关系,只有在发生重大故障时才会意识到这些依赖关系,即使您在分布式系统设计方面与 AWS 一样有经验。

但让我们暂时只关注 Kinesis。 Kinesis 提供的 SLA 规定:

AWS 将尽商业上合理的努力使每个 AWS 区域在任何月度计费周期内的每个包含服务 4 的月正常运行时间百分比至少达到 99.9%(“服务承诺”)。

请注意该句子中的“商业上合理”。这不是不惜一切代价保持的保证,但前提是它在商业上对 AWS 有意义。如果他们不能遵守 SLA 的承诺,他们会提供补偿:

如果包含的服务不符合服务承诺,您将有资格获得如下所述的服务积分。

下表列出了根据计费周期内包含服务的实际可用性而定的补偿金额:

 

Monthly Uptime Percentage Service Credit Percentage
Less than 99.9% but equal to or greater than 99.0% 10%
Less than 99.0% but equal to or greater than 95.0% 25%
Less than 95.0% 100%

 

IMO 这是一个大胆的承诺。我不知道有任何 IT 部门为其本地基础设施提供甚至接近的 SLA——而且本地基础设施的复杂性比 AWS 提供的基础设施要简单几个数量级。因此,从我的角度来看,关于 SLA 没有什么可抱怨的。

但是,这就是重点:它不是 100% 的可用性保证

一个月内 99.9% 的可用性意味着您每月仍有超过 43 分钟的不可用时间。这意味着您每月可以轻松丢失 10.000 条消息,而 AWS 不会违反其 99.9% 的可用性承诺。 

如果 Kinesis 在一个月内停机最多 7.2 小时,您将少付 10% 的 Kinesis 账单,而对于每月最多 1.5 天的停机时间,您将少付 25%。仅当相关月份的停机时间超过 1.5 天时,您才无需支付任何费用。关于最近的 AWS 中断,这意味着受影响的公司可能会在下个月的 Kinesis 账单中获得 10% 或 25% 的信用额度。

请注意,这不包括因停电造成的收入损失或其他问题的补偿。

再说一遍:我认为 Kinesis SLA 非常好。但是,如果您将此 SLA 与 100% 可用性保证混淆并押注于持续正常运行时间,那么您就错了。

这只是关于使用 Kinesis。任何重要的基于云的应用程序都使用多种服务,通常是十几个或更多。如果您浏览他们的 SLA,您将获得类似的可用性承诺 。

现在让我们假设,您使用 10 个服务。为简单起见,让我们另外假设使用的所有服务都提供与 Kinesis 相同(良好)的 SLA。

重点是:使用的所有部件的可用性成倍增加!

这意味着:如果您使用 10 项具有 99.9% 可用性承诺的服务,那么总体而言,您使用的组合服务的可用性承诺将下降到 99%——如果它们完全不相关 . 如果它们具有依赖关系(正如我们在整个中断),预期可用性较低。这意味着如果所有服务都遵守其 99.9% 的可用性承诺,则在一个月内至少有 7.2 小时的可预期不可用性。

换句话说:如果没有额外的措施,您需要为平均云应用程序每月的一个工作日(从 9 到 5 个)不可用的基础设施做好准备。如果从这个角度来看,停电并没有什么特别之处。无论如何,这只是您需要期待的事情。这个故事令人惊讶的部分是这样的中断很少发生。

也许 AWS 做得太好了,通常远远超出了他们的承诺,结果客户认为可用性是理所当然的,如果预期发生,就会变得草率并抱怨很多。媒体也加入进来。

但最后,步履蹒跚的公司很可能没有足够仔细地评估 SLA。都在里面。你只需要做数学。

本地环境中的相同模式


总而言之,似乎步履蹒跚的公司

  • 不了解分布式系统的效果不够好
  • 陷入 100% 可用性陷阱
  • 没有足够仔细地评估提供的 SLA。

但公平地说:这种心态和由此产生的行为不仅限于公共云的使用。我们随处可见。 

我们在本地场景中看到的更多,其中数据库、消息队列、事件总线、容器调度程序、VM 管理程序等都被视为 100% 可用 - 但事实并非如此。此外,在设计在此基础架构上运行的应用程序之前,他们的 SLA(通常比我们看到的 Kinesis SLA 更差)通常没有得到足够仔细的评估。

此外,通常认为远程应用程序在本地环境中 100% 可用。在许多微服务实现中可以观察到相同的效果,其中所有其他服务都被认为是 100% 保证的。

当人们在他们呼吁使用服务网格、Apache Kafka 等时发现这种假设是错误的,并期望这些额外的基础设施能够很好地解决他们的问题——再次陷入 100% 可用性陷阱。

韧性与混沌工程


正如我在这篇文章的开头所写的,不管你怎么看:

  • 在分布式系统中,跨进程边界的事情会出错。
  • 你无法预测什么时候会出错。
  • 它会在应用程序级别打击你。

尤其是最后一句话很重要:它将在应用程序级别打击您。这就是您需要韧性工程的原因。 

韧性工程可让您系统地评估业务用例的重要性,检查潜在的故障模式并决定对策。如果操作正确,它是一种强大的风险管理工具,还可以考虑您行为的经济后果。

关于 AWS 中断,韧性工程会问如果发生更长时间的云基础设施中断会产生什么后果。如果影响太大,下一个活动是确定最关键的用例。然后识别潜在的故障场景并定义对策。

最后,这是简单的风险管理:你能承受多少停机时间,你想怎么做? 

通常,性工程与混沌工程相辅相成。性工程可帮助您解决已知的故障模式,而混沌工程可帮助您检测未知的故障模式(并验证性措施的有效性)。 

与探索性测试类似,您可以模拟任意故障情况并观察系统如何响应它。请注意,您始终小心控制故障模拟(称为“实验”)的“爆炸半径”,即限制实验的潜在影响。

通常,你会在所谓的“游戏日”中捆绑一整套实验。在更高级的组织中,您不断运行故障模拟并观察结果。

即使这个术语听起来有点儿戏,混沌工程也绝不是一场游戏。它是风险管理的重要组成部分。如果您有必须启动并运行的关键用例,则需要探索未知的故障源。在分布式系统中,这不是可选的,但可以决定成败。

您可能会争辩说您没有时间或预算。好吧,步履蹒跚的公司可能采取同样的方式。问题是:这些公司在停电期间没有完成韧性和混乱工程作业,损失了多少金钱和声誉?他们中的一些人可能无法幸免于难。

因此,您需要问自己一个问题:您负担得起吗?

就个人而言,我认为大多数公司都不能忽视韧性和混沌工程。他们中的一些人仍然忽略它,希望事情会顺利进行。但如果涉及风险管理,希望是一个糟糕的顾问。

总结起来


这篇博文比我预期的要长得多,而且我承认我只是触及了表面。我的主要信息是:

  • 说在中断期间运行在其基础设施上的应用程序停机是 AWS 的唯一错误,IMO 是不正确的。
  • 步履蹒跚的公司对分布式系统的影响不够了解,并陷入了 100% 可用性陷阱。
  • 步履蹒跚的公司对 SLA 的评估不够好。从 SLA 的角度来看,中断是意料之中的事。
  • 韧性工程有助于评估和减轻可用性,从而降低经济(或更糟)风险。这不仅仅是一场 IT 秀,而是业务和 IT 的共同努力。
  • 混沌工程通过发现未知的故障模式来增强性工程
  • 性和混沌工程是当代风险管理的重要、非可选工具。忽略它们意味着让自己步履蹒跚——或者更糟。

还有很多话要说,但帖子已经太长了。我将在以后的帖子中更详细地讨论讨论的主题。但是现在,我将把它留在那里,希望我能给你一些想法来思考。

原文:https://www.ufried.com/blog/resilience_engineering/

本文:https://jiagoushi.pro/node/2138

SEO Title
THE IMPORTANCE OF RESILIENCE ENGINEERING

【韧性架构设计】分布式系统的韧性

Chinese, Simplified

由许多协同工作的微服务组成的云原生应用程序架构形成了一个分布式系统。确保分布式系统可用——减少其停机时间——需要提高系统的弹性。弹性是使用提高可用性的策略。弹性策略的示例包括负载平衡、超时和自动重试、截止日期和断路器。

弹性可以通过不止一种方式添加到分布式系统中。例如,让每个微服务的代码都包含对具有弹性功能的代码库的调用,或者让特殊的网络代理处理微服务请求和回复。弹性的最终目标是确保特定微服务实例的故障或降级不会导致导致整个分布式系统停机的级联故障。

在分布式系统的上下文中,弹性是指分布式系统能够在不利情况发生时自动适应以继续服务于其目的。

术语“可用性”和“弹性”具有不同的含义。可用性是分布式系统启动的时间百分比。弹性是使用策略来提高分布式系统的可用性。

弹性的主要目标之一是防止一个微服务实例的问题导致更多问题,这些问题升级并最终导致分布式系统故障。这被称为级联故障。

弹性策略


分布式系统的弹性策略通常用于 OSI 模型的多个层,如图所示。例如,物理和数据链路层(第 1 层和第 2 层)涉及物理网络组件,例如与 Internet 的连接,因此数据中心和云服务提供商将负责为这些层选择和实施弹性策略。

Layer 7 Resilience Strategy

应用层是应用驻留的地方;这是人类用户(以及其他应用程序)直接与之交互的层。应用程序级(第 7 层)弹性策略内置于微服务本身。组织的开发人员可以设计和编写应用程序,使其在降级状态下继续工作,提供重要功能,即使其他功能由于一个或多个微服务的错误、妥协或其他问题而失败。

在流行的视频流应用程序的推荐功能中可以看到此类功能的一个示例。大多数时候主页包含个性化推荐,但如果相关的后端组件出现故障,则会显示一系列通用推荐。此故障不会影响您搜索和播放视频的能力。

传输层(第 4 层)提供网络通信能力,例如确保可靠的通信传输。网络级弹性策略在第 4 层工作,以监控每个微服务已部署实例的网络性能,并将微服务使用请求定向到最佳实例。例如,如果某个特定的微服务实例由于其所在位置的故障(例如网络中断)而停止响应请求,则新请求将自动定向到该微服务的其他实例。

将云原生应用程序部署为分布式系统的组织应考虑网络和/或应用程序级别的弹性策略。在这里,我们将研究云原生应用程序的四种此类策略:

  • 负载均衡
  • 超时和自动重试
  • 截止日期
  • 断路器

负载平衡、超时和自动重试支持分布式系统组件的冗余。截止日期和断路器有助于减少分布式系统任何部分的降级或故障的影响。

负载均衡


云原生应用程序的负载平衡可以在 OSI 模型的多个层执行。就像我们刚刚讨论的弹性策略一样,负载平衡可以在第 4 层(网络或连接级别)或第 7 层(应用程序级别)执行。

对于 Kubernetes,第 4 层负载均衡默认使用 kube-proxy 实现。它在网络连接级别平衡负载。 Pod IP 地址的管理和虚拟/物理网络适配器之间的流量路由是通过容器网络接口 (CNI) 实现或覆盖网络(例如 Calico 或 Weave Net)来处理的。

回到第 4 层负载均衡,假设一个网络连接每秒向一个应用程序发送一百万个请求,而另一个网络连接每秒向同一个应用程序发送一个请求。负载均衡器不知道这种差异;它只看到两个连接。如果它将第一个连接发送到一个微服务实例,并将第二个连接发送到第二个微服务实例,它会认为负载是平衡的。

第 7 层负载平衡基于请求本身,而不是连接。第 7 层负载均衡器可以看到连接中的请求,并将每个请求发送到最佳微服务实例,这可以提供比第 4 层负载均衡器更好的均衡。一般来说,当我们说“负载平衡”时,我们指的是第 7 层负载平衡。此外,虽然第 7 层负载均衡可以应用于服务或微服务,但这里我们只关注将其应用于微服务。

对于云原生应用程序,负载平衡是指在微服务的运行实例之间平衡应用程序的请求。负载均衡假设每个微服务有多个实例;每个实例都有多个实例提供了冗余。只要可行,实例都是分布式的,因此如果特定服务器甚至站点出现故障,并非任何微服务的所有实例都将变得不可用。

理想情况下,每个微服务都应该有足够的实例,这样即使发生故障(例如站点中断),每个微服务仍然有足够的可用实例,以便分布式系统继续为当时需要它的所有人正常运行。

负载平衡算法


有许多用于执行负载平衡的算法。让我们仔细看看其中的三个。

  • 轮询是最简单的算法。每个微服务的实例轮流处理请求。例如,如果微服务 A 有三个实例——1、2 和 3——第一个请求将发送到实例 1,第二个发送到实例 2,第三个发送到实例 3。一旦每个微服务收到请求,下一个请求将分配给实例 1 以开始另一个循环通过实例。
  • 最少请求是一种负载均衡算法,它将新请求分发给当时待处理请求最少的微服务实例。例如,假设微服务 B 有四个实例,实例 1、2 和 3 现在分别处理 10 个请求,但实例 4 只处理两个请求。使用最小请求算法,下一个请求将转到实例 4。
  • 会话亲和性,也称为粘性会话,是一种尝试将会话中的所有请求发送到相同微服务实例的算法。例如,如果用户 Z 正在使用一个应用程序并导致请求被发送到微服务 C 的实例 1,那么在同一用户会话中对微服务 C 的所有其他请求都将被定向到实例 1。

这些算法有许多变体——例如,加权通常被添加到循环和最小请求算法中,这样一些微服务实例接收的请求份额比其他微服务实例更大或更小。例如,您可能希望支持通常比其他人更快地处理请求的微服务实例。

在实践中,单独的负载平衡算法通常不能提供足够的弹性。例如,它们会继续向已经失败且不再响应请求的微服务实例发送请求。这就是添加超时和自动重试等策略的好处。

超时和自动重试


超时是任何分布式系统的基本概念。如果系统的一部分发出请求,而另一部分在一定时间内未能处理该请求,则请求超时。然后,请求者可以使用系统故障部分的冗余实例自动重试请求。

对于微服务,在两个微服务之间建立并强制执行超时。如果微服务 A 的实例向微服务 B 的实例发出请求,而微服务 B 的实例没有及时处理,则请求超时。然后,微服务 A 实例可以使用微服务 B 的不同实例自动重试请求。

无法保证在超时后重试请求会成功。例如,如果微服务 B 的所有实例都有相同的问题,则对其中任何一个的请求都可能失败。但是,如果只有一些实例受到影响——例如,一个数据中心的中断——那么重试很可能会成功。

此外,请求不应总是自动重试。一个常见的原因是避免意外复制已经成功的事务。假设从微服务 A 到微服务 B 的请求被 B 成功处理,但它对 A 的回复延迟或丢失。在某些情况下可以重新发出此请求,但在其他情况下则不行。

  • 安全事务是相同请求导致相同结果的事务。这类似于 HTTP 中的 GET 请求。 GET 是一个安全事务,因为它从服务器检索数据但不会导致服务器上的数据被更改。多次读取相同的数据是安全的,因此重新发出安全事务的请求应该没问题。安全事务也称为幂等事务。
  • 不安全的事务是相同请求导致不同结果的事务。例如,在 HTTP 中,POST 和 PUT 请求是潜在的不安全事务,因为它们将数据发送到服务器。复制请求可能会导致服务器不止一次地接收该数据并可能不止一次地处理它。如果交易正在授权付款或订单,您当然不希望它发生太多次。


截止日期


除了超时,分布式系统还有所谓的分布式超时,或者更常见的是截止日期。这些涉及系统的两个以上部分。假设有四个相互依赖的微服务:A 向 B 发送请求,B 对其进行处理并将自己的请求发送给 C,C 对其进行处理并向 D 发送请求。回复以另一种方式流动,从 D 流向 C ,C 到 B,B 到 A。

下图描述了这种情况。假设微服务 A 需要在 2.0 秒内回复其请求。在最后期限内,完成请求的剩余时间与中间请求一起移动。这使每个微服务能够优先处理它收到的每个请求,并且当它联系下一个微服务时,它会通知该微服务剩余的时间。

Deadlines and distributed timeouts

断路器


超时和截止日期分别处理分布式系统中的每个请求和回复。断路器对分布式系统有更多的“全局”视图。如果一个特定的微服务实例没有回复请求或者回复请求的速度比预期的慢,那么断路器可能会导致后续请求被发送到其他实例。

断路器通过为单个微服务实例设置服务降级或故障程度的限制来工作。当实例超过该级别时,会触发断路器并导致微服务实例暂时停止使用。

断路器的目标是防止一个微服务实例的问题对其他微服务产生负面影响并可能导致级联故障。问题解决后,可以再次使用微服务实例。

级联故障通常是由于针对经历降级或故障的微服务实例的自动重试而开始的。假设您有一个微服务实例,请求不堪重负,导致它响应缓慢。如果断路器检测到这一点并暂时阻止新请求进入实例,则实例有机会赶上其请求并恢复。

但是,如果断路器不动作并且新请求继续发送到实例,则该实例可能会完全失败。这会强制所有请求转到其他实例。如果这些实例已经接近容量,新请求也可能使它们不堪重负并最终导致它们失败。这个循环继续下去,最终整个分布式系统都失败了。

使用库实施弹性策略


到目前为止,我们已经讨论了几种弹性策略,包括三种形式的负载平衡加上超时和自动重试、截止日期和断路器。现在是时候开始考虑如何实施这些策略了。

首次部署微服务时,实施弹性策略的最常见方法是让每个微服务使用支持一个或多个策略的标准库。 Hystrix 就是一个例子,它是一个为分布式系统添加弹性特性的开源库。由 Netflix 开发到 2018 年,Hystrix 调用可以包裹在一个微服务中依赖于另一个微服务请求的任何调用。弹性库的另一个示例是 Resilience4j,它旨在用于使用 Java 进行函数式编程。

通过应用程序库实施弹性策略当然是可行的,但它并不适用于所有情况。弹性库是特定于语言的,微服务开发人员通常为每个微服务使用最好的语言,因此弹性库可能不支持所有必要的语言。为了使用弹性库,开发人员可能必须使用提供不理想性能或具有其他重大缺陷的语言编写一些微服务。

另一个问题是依赖库意味着为每个微服务中的每个易受攻击的调用添加调用包装器。一些调用可能会丢失,一些包装可能包含错误——让所有微服务的所有开发人员一致地做事情是一个挑战。还有维护问题——未来每个从事微服务工作的新开发人员都必须了解调用包装器。

使用代理实施弹性策略


随着时间的推移,基于库的弹性策略实现已被基于代理的实现所取代。

一般来说,代理位于两方之间的通信中间,并为这些通信提供某种服务。代理通常在两方之间提供某种程度的分离。例如,A 方向 B 方发出请求,但该请求实际上是从 A 发送到代理,代理处理该请求并将自己的请求发送给 B。A 和 B 不直接相互通信。

下图显示了这种通信流程的示例。一个会话发生在微服务 A 的实例及其代理之间,一个单独的会话发生在 A 的代理和微服务 B 的实例之间。A 到代理和代理到 B 会话共同提供 A 和B.

Resilience Strategies with Proxies

在分布式系统中,代理可以在微服务实例之间实现弹性策略。继续前面的示例,当微服务 A 的实例向微服务 B 发送请求时,该请求实际上会发送到代理。代理会处理 A 的请求并决定它应该转到哪个微服务 B 的实例,然后它会代表 A 发出请求。

代理会监视来自 B 实例的回复,如果没有及时收到回复,它可以自动使用不同的微服务 B 实例重试请求。图中,微服务 A 的代理有微服务 B 的三个实例可供选择,它选择了第三个。如果第三个实例的响应速度不够快,则代理可以使用第一个或第二个实例来代替。

基于代理的弹性的主要优点是无需修改单个微服务即可使用特殊库;任何微服务都可以被代理。

原文:https://www.getambassador.io/learn/service-mesh/resilience-for-distribu…

本文:https://jiagoushi.pro/node/2156

SEO Title
Resilience for distributed systems

【韧性架构设计】确保您的应用程序具有网络韧性的 5 种方法

Chinese, Simplified

由 COVID-19 大流行引起的大规模转向远程工作,提高了许多组织对弹性应用安全实践的需求。

除了应对这些天应用程序发布的大量和频率之外,应用程序安全团队现在还必须应对与远程工作和签入来自全球各地的代码相关的挑战。

随着应用程序每周、每天甚至每小时发布到生产环境中,DevSecOps 中的“秒”确实从未像现在这样相关或重要。是时候确保您的应用安全方法具有网络弹性了。这里有五个需要关注的领域。

1.自动化


自动化对于网络弹性至关重要。您需要利用工具,以使应用安全解决方案尽可能无接触和流程驱动。理想情况下,任何可以自动化的东西都应该是自动化的,而弹性系统将允许这样做。事实上,一个有弹性的系统不仅会允许它,而且还会推动自动化。

想象一下未来的环境,如果您需要突然扫描 1,000 个应用程序,您可以自动增加处理该容量所需的扫描仪数量。如果容量发生变化并且您不再需要那么多扫描仪,那么您的系统就足够智能,可以解决这个问题并自动降低数量。

在一个真正有弹性的系统中,自动化将允许开发人员编写和提交代码,并且扫描就会发生。你不应该做任何事情。系统会自动删除您无法修复的内容、在您的环境中不重要的内容、或您的 KPI 和类似性质的内容。这几乎就像您踩下汽车的油门踏板一样。有很多事情要做,但你不需要知道引擎除了它所做的任何事情。这是相当强大的。

最终,目标应该是拥有像拼写检查器一样自我修复的代码。我们还没有到那一步,但有一天会有足够的智能让你相信系统可以自行修复问题。

2. 有可操作的结果


您的应用安全计划应专注于推动测试结果的可操作性。它应该以您今天需要关注的事情为中心。从历史上看,当您真正需要的只是与组织和您相关的问题列表时,应用程序安全解决方案倾向于为您提供要解决的问题的清单。

一个有弹性的系统将专注于你今天需要解决的 10 件事,而不是你可能需要随着时间的推移解决的 1000 件事。它使用智能来识别可能影响或阻止您投入生产的问题。

可操作性是自动化的一部分。这意味着开发人员可以编写一些代码,而在幕后对代码进行评估并尽快显示相关且需要修复的内容。这就像从一匹马和一辆马车变成一辆特斯拉。

3.支持更频繁的扫描


您将代码安全地发布到生产环境中的能力以及遥测的速度在很大程度上取决于您能够扫描应用程序的频率。您需要应用程序安全性的弹性,因为您拥有更多应用程序并且您正在更频繁地扫描它们。这给应用安全团队、开发人员和 CISO 带来了很大压力。

弹性系统支持可扩展的扫描容量,从 1 次扫描到 1+n 次。虽然可扩展性与扫描仪数量和您拥有的应用程序数量有关,但弹性系统中的频率与您扫描这些应用程序的频率有关。

例如,如果您使用 GitHub 并且您每天扫描或提交 20 次,则您需要有一个足够有弹性的系统来处理该频率。这是关于具有突发功能,可以在达到阈值时打开更多扫描,而无需打电话给某人或去寻找其他产品。比如说,你只需在 Docker 中启动另一个容器,就完成了。

4. 覆盖范围广


现代 Web 应用程序非常受 Web 服务驱动,您拥有的 Web 服务和 API 越多,应用程序的风险就越大。弹性是指拥有一个应用安全解决方案,它不仅可以解决您现在正在做的事情,而且还具有应对未来挑战的灵活性和可扩展性。

您的解决方案需要与云无关,并具有涵盖本地和 SaaS 环境的灵活性。它应该能够快速支持新的语言和框架。覆盖面广度意味着支持企业现在和未来需要扫描的各种语言。大多数企业不仅仅拥有 .NET 或 Java,它们还拥有数十种语言。

如果您从 .NET 商店开始,并且拥有 .NET 的静态分析功能,那么如果有新团队加入或收购另一家公司,您是否有能力支持 Java?还是您需要出去购买一套全新的产品?一个有弹性的应用程序安全系统将能够扫描这些新应用程序,您可以简单地决定要利用哪种模型,从 SaaS 或内部部署到混合。

5. 确保它是可扩展的


在弹性系统中,您无需添加基础架构即可获得更多扫描功能。您的系统将与云无关,并且能够按需启动扫描服务器,并在您不需要它们时同样轻松地关闭它们。只需几分钟,您就可以从需要额外容量来扫描更多应用程序转变为仅打开额外容量。

许可灵活性对于可扩展性至关重要。它需要足够灵活,这样您就不必在每次需要额外容量进行静态或动态测试时都购买另一个许可证。您的许可证应该允许您根据需要和扫描容量来回移动。

为什么网络弹性是关键


Verizon 年度数据泄露调查报告的最新版本显示,Web 应用程序漏洞是网络犯罪分子的首要目标。 Verizon 在 2019 年调查的数据泄露事件中,约有 40% 实际上涉及应用程序漏洞。

很明显:强大的应用程序安全计划对企业网络弹性至关重要。按照上面的指导来改变你的方法。

保持学习

 

  • 未来是安全即代码。通过 TechBeacon 指南了解 DevSecOps 如何帮助您实现目标。另外:请参阅 SANS DevSecOps 调查报告,了解对从业者的重要见解。
  • 使用 TechBeacon 指南快速了解应用程序安全测试的状态。另外:获取 Gartner 的 2021 年 AST 魔力象限。
  • 通过 TechBeacon 的 2021 年应用程序安全工具指南了解应用安全工具领域。
  • 下载免费的 Forrester Wave 静态应用程序安全测试。另外:在此网络研讨会中了解 SAST-DAST 组合如何提高您的安全性。
  • 了解 API 安全需要访问管理的五个原因。
  • 了解如何为未来十年制定应用安全策略,并在应用安全开发人员的生活中度过一天。
  • 使用 TechBeacon 指南构建现代应用安全基础。

原文:https://techbeacon.com/security/5-ways-ensure-your-applications-are-cyb…

本文:

SEO Title
5 ways to ensure your applications are cyber resilient

【韧性架构设计】软件韧性:从意外中恢复的 7 个必备因素

Chinese, Simplified

软件弹性是任何可扩展、高性能和容错软件的必备品质。

软件从意外事件中恢复的能力是软件弹性。 这意味着软件工程师必须预测意外事件并对其进行解释。 创建这种容错的解决方案可以在代码中或在基础设施层上。

分布式系统会失败,一个有弹性的软件系统不会试图避免失败,而是期待它并优雅地响应。

在这篇文章中,我们将研究您需要注意的一些方面,以实现软件弹性。

目录

  • 什么是软件弹性
  • 弹性软件因素
    • 逐步推出/部署
    • 重试软件弹性
    • 弹性软件的超时
    • 倒退
    • 幂等操作支持软件弹性
    • 数据库事务
    • 速率限制
  • 其他需要考虑的事项
  • 结论

什么是软件弹性


卡内基梅隆大学软件工程学院博客指出:

基本上,如果一个系统在逆境中继续执行其任务(即,如果它提供所需的能力,尽管可能导致中断的过度压力)。具有弹性很重要,因为无论系统设计得多么好,现实迟早会合谋破坏系统。

如果软件系统在发生意外事件时能够部分正常运行,这就是软件弹性。在基础设施层面,有 NetFlix 臭名昭著的 Chaos Monkey。 Chaos Monkey 进入您的生产环境并随机开始杀死实例。这可以作为软件弹性的压力测试。

软件弹性也受到爆炸半径的影响。如果就其可以覆盖的半径而言,变更风险较低,则更容易进行变更。如果爆炸半径非常大,您可能还需要考虑其他事情。

弹性软件因素


有多个因素是软件弹性方程的一部分。以下是我在十多年的软件工程职业生涯中的一些经验。

下面提到的示例将与电子商务有关,因为我已经在时尚电子商务领域工作了将近 9 年。

让我们开始吧。

逐步推出/部署


逐步推出或部署是允许访问部分版本的能力。它可能是金丝雀部署或蓝绿色部署,或者只是一个功能标志,甚至是滚动部署。您可以以丰富多彩的方式阅读有关这些部署技术的更多信息。

这里的重点是,即使这是一项手动任务,它对于弹性软件也非常重要。想象一下,您正在更改电子商务网站的支付网关。如果你进行一次大爆炸,100% 的交易从以前的支付网关 A 转到新的支付网关 B,你将陷入困境。

但是,如果您可以像 1% 的客户一样试用 1 周,那么通过新的网关集成来消除任何错误会很有帮助,并且爆炸半径仅为交易的 1%。

慢慢地,你可以从 1 到 5,然后到 10,最后到 100,充满信心。在部署时进行健康检查也是如此。如果运行状况检查失败,部署将自动回滚。根据服务的不同,您甚至可以逐步推出,这意味着这个特定版本只能获得 2% 的流量。运行在基础设施层而非代码层上的 Google Cloud 等服务支持逐步推出。

弹性软件的另一个重要考虑因素是部署而不是发布。

重试软件弹性


如果您调用另一个系统,您总是需要期望它们可能会失败。因此,在这种情况下,重试机制会有所帮助。例如,您正在调用产品评论服务来创建新的产品评论。

如果它未能创建评论,您可以轻松地重试 1 或 2 次以获得成功的响应。

下面是一个非常简单的 curl 示例:

curl -i --retry 3 http://httpbin.org/status/500

这里的 curl 总是会重试 3 次,因为它会返回 500 错误。 下面的 curl 只会运行一次,因为它会在第一次尝试时返回 200:

curl -i --retry 3 http://httpbin.org/status/200

重试是使软件更具弹性的一种简单但有效的方法。

弹性软件的超时


外部系统可能很慢,您无法控制它们的响应时间。这反过来又会使您开发的系统变慢。一旦我们与“流行”的快递服务集成。不幸的是,他们创建货件的响应时间是几秒钟而不是几毫秒。

我们通过最佳超时解决了这个问题,并在可能的情况下推动任务异步。这确实有助于保持软件弹性完好无损。

这解除了进行质量检查并将物品放入盒子中以运送给客户的人员的障碍。当箱子从 QC 站运送到包装站时,将创建装运并打印运输标签。尽管盒子从 QC 到包装站需要几秒钟的时间,但这足以让我们创建货物。如果某些发货失败,有一个简单的重试选项,即按需致电快递员。

故事的寓意,总是添加相关的超时并快速失败。根据需要为用户提供一种在需要时手动重试的方法。超时非常重要。

倒退


回退是一个非常简单的概念。如果主要的东西不起作用,请使用备份。对于 Web 系统来说,主要的事情可以是来自 API 的响应。因此,如果您的 API 调用在重试后仍然失败,您可以回退到响应的本地副本。

另一个纯代码的例子可以很简单:

const shippingFee = fees.shipping ? fees.shipping: 10.00;

在上面的代码片段中,它会查找 fee.shipping 如果不可用,它会回退到 10.00 的值。我们可以在 API 调用中实现相同的功能,如果我们没有从 API 调用中得到想要的结果,它将优雅地降级为使用默认值。

回退似乎很明显,但有时我看到它们被遗忘或省略。

这可能会导致高流量系统出现问题。

幂等操作支持软件弹性


一个堆栈溢出答案总结得很好:

在计算中,幂等操作是指使用相同的输入参数多次调用它时不会产生额外影响的操作。

在现实生活中,它就像公共汽车上的那个停止按钮。停车标志亮起后按一次或100次,效果相同,指示公交车司机在下一个公交车站停车。例如,API 中的 GET 操作是幂等的。这对于设计弹性系统很重要,让我用一个例子来解释一下。

您正在设计一个 API 来将消息标记为已读。

无论调用多少次 API 将单条消息标记为已读,第一个都将其从未读设置为已读,并且所有其他都不会更改状态。

这是一个易于理解的幂等性示例。在使您的系统具有弹性时,您可以安全地忽略第二个和以后的请求,以保留您的资源。

数据库事务


理解数据库事务的最简单方法是全有或全无。如果您有 3 个步骤来完成一项任务,并且在第 2 步中存在问题,它将回滚整个操作。

一个典型的例子是两个银行账户之间的汇款,要么全部通过,要么什么也没发生。

不应该出现A账户扣款但B账户没有充值的情况。数据库事务对于数据的一致性非常重要。

通过充分利用隔离级别,我们可以使用数据库事务来应对竞争条件。例如,一个 cron 将更新 20 条记录,如果这些行与另一个系统(如 ERP)成功同步,则名为 synced 的标志将设置为 true。可以通过以下步骤完成,以避免另一个 cron 同时执行相同的任务:

  1. 准备基础任务,例如将这些行与企业资源规划 (ERP) 软件同步
  2. 启动数据库事务
  3. SELECT … FOR UPDATE,隔离级别已提交,会话超时时间比平时长
  4. 将行与 ERP 同步
  5. 使用更新查询将所选行的同步标志设置为 1
  6. 提交交易
  7. 如果有任何问题,回滚整个事务

因此,在上述情况下,如果第 4 步失败,事务将回滚。当行被 select for update 锁定时,另一个 cron 将无法读取它,因为它被锁定为 UPDATE 并且在隔离级别读取提交的情况下完成。

这有助于通过停止同步相同的行两次来创建容错和弹性软件。如果另一个 cron 甚至在第一个 cron 运行时错误地运行,它将等待这些行可以被新的 SELECT ... FOR UPDATE 查询自由读取。

速率限制


到现在为止,您肯定已经发现,要使软件更具弹性,就需要以最佳方式使用资源。这个速率限制因素正在避免我们的资源被滥用。例如,Twitter API 速率限制调用。让我们以 Twitter API 上的 /statuses/user_timeline 为例,它显示“900 个请求/15 分钟窗口(用户身份验证)”和“100,000 个请求/24 小时窗口(应用程序级别)”。因此,如果作为消费者,您拨打超过 900 次电话以获取用户的雕像,则会收到状态码为 429 的响应。

开发 API 时必须遵循相同的原则,即使它们被其他内部服务使用。让我们假设如果其他内部服务之一有一个错误配置的无限循环,那么当它开始疯狂地攻击您的服务时,您的服务将停机。

如果您有一个良好的速率限制,其他服务将尽早开始发现错误,他们可以更快地解决问题。

最后,您的服务不会占用资源,也不会通过更快地失败来保持正常。

其他需要考虑的事项


为了获得更好的软件弹性,还有许多其他事情需要考虑。数据库读写隔离是一种很好的做法。其中有一个主要用于写入和多个读取副本的主数据库。

在这种情况下,读取的大部分操作在读取副本之间进行负载平衡,并且主节点获得写入。

主服务器与只读副本同步可能会有“几秒钟”的延迟,但这是您应该愿意为它提供的弹性支付的成本。

另一个重要的软件弹性模式是断路器模式。

类似于您家的断路器,如果您的软件系统多次无法访问另一个软件系统,它会破坏标记它打开的电路。它会定期检查其他系统是否已恢复。

当另一个系统恢复时,电路再次闭合。微软博客对断路器模式有很好的解释。

弹性软件系统自动扩展。它们根据负载累加资源。这一点也和软件的可扩展性有关,一般软件可扩展性和弹性是齐头并进的。自动缩放系统依赖于健康检查。

对于具有弹性负载的系统,它们应该能够在负载高时添加资源,并在流量下降时降低资源。

这使软件保持弹性并且成本也处于最佳状态。

结论


弹性和自我修复软件对于高正常运行时间非常重要。

即使在逆境的情况下,软件性能可能会降低但功能性能是弹性软件的标志。

软件弹性是通过始终质疑如果失败会发生什么来实现的,尤其是在与数据库或外部 API 等外部服务通信时。我希望这可以帮助您构建更具弹性的软件。如果您还有其他方面要分享,请不要忘记发表评论。

原文:https://geshan.com.np/blog/2020/12/software-resilience/

本文:

SEO Title
Software Resilience: 7 must-have factors for healing from the unexpected

【韧性设计】节流模式

Chinese, Simplified

控制应用程序实例、单个租户或整个服务使用的资源消耗。这可以使系统继续运行并满足服务水平协议,即使需求增加对资源造成极大负载。

背景和问题


云应用程序的负载通常会根据活动用户的数量或他们正在执行的活动类型而随时间变化。例如,更多用户可能会在工作时间处于活跃状态,或者系统可能需要在每个月底执行计算成本高昂的分析。活动中也可能出现突然的和意料之外的爆发。如果系统的处理需求超过了可用资源的容量,那么它的性能就会很差,甚至会失败。如果系统必须满足商定的服务水平,则此类故障可能是不可接受的。

有许多策略可用于处理云中的不同负载,具体取决于应用程序的业务目标。一种策略是使用自动缩放在任何给定时间将供应的资源与用户需求相匹配。这有可能始终如一地满足用户需求,同时优化运行成本。但是,虽然自动缩放可以触发额外资源的配置,但这种配置并不是立即的。如果需求快速增长,可能会出现资源短缺的时间窗口。

解决方案


自动缩放的另一种策略是允许应用程序仅在某个限制内使用资源,然后在达到此限制时限制它们。系统应该监控它是如何使用资源的,以便当使用量超过阈值时,它可以限制来自一个或多个用户的请求。这将使系统能够继续运行并满足任何现有的服务水平协议 (SLA)。有关监控资源使用情况的更多信息,请参阅 Instrumentation and Telemetry Guidance。

该系统可以实施多种节流策略,包括:

  • 拒绝在给定时间段内每秒访问系统 API 超过 n 次的单个用户的请求。这需要系统计量每个租户或运行应用程序的用户的资源使用情况。有关详细信息,请参阅服务计量指南。
  • 禁用或降低选定非必要服务的功能,以便必要服务可以在有足够资源的情况下畅通无阻地运行。例如,如果应用程序正在流式传输视频输出,它可以切换到较低的分辨率。
  • 使用负载均衡来平滑活动量(基于队列的负载均衡模式更详细地介绍了这种方法)。在多租户环境中,这种方法会降低每个租户的性能。如果系统必须支持具有不同 SLA 的租户组合,则可能会立即执行高价值租户的工作。可以推迟对其他租户的请求,并在积压情况缓解后进行处理。优先队列模式可以用来帮助实现这种方法。
  • 推迟代表较低优先级的应用程序或租户执行的操作。这些操作可以暂停或限制,但会生成一个异常通知租户系统正忙,稍后应重试该操作。

该图显示了使用三个功能的应用程序的资源使用(内存、CPU、带宽和其他因素的组合)与时间的面积图。特性是功能的一个区域,例如执行一组特定任务的组件、执行复杂计算的一段代码或提供诸如内存缓存之类的服务的元素。这些特征标记为 A、B 和 C。

Figure 1 - Graph showing resource use against time for applications running on behalf of three users

特性线正下方的区域指示应用程序在调用此特性时使用的资源。例如,功能 A 的线下方的区域显示正在使用功能 A 的应用程序使用的资源,功能 A 和功能 B 的线之间的区域表示调用功能 B 的应用程序使用的资源。聚合区域每个功能都显示系统的总资源使用情况。

上图说明了延迟操作的影响。就在时间 T1 之前,分配给使用这些功能的所有应用程序的总资源达到阈值(资源使用限制)。此时,应用程序有耗尽可用资源的危险。在这个系统中,功能 B 不如功能 A 或功能 C 重要,因此它被暂时禁用并且它正在使用的资源被释放。在时间 T1 和 T2 之间,使用功能 A 和功能 C 的应用程序继续正常运行。最终,这两个功能的资源使用减少到在时间 T2 有足够的容量再次启用功能 B 的程度。

自动缩放和限制方法也可以结合使用,以帮助保持应用程序响应并在 SLA 范围内。如果预计需求将保持高位,则在系统横向扩展时,节流提供了一种临时解决方案。此时,可以恢复系统的全部功能。

下图显示了系统中运行的所有应用程序对时间的总体资源使用情况的区域图,并说明了如何将限制与自动缩放结合起来。

Figure 2 - Graph showing the effects of combining throttling with autoscaling

在时间 T1,达到指定资源使用的软限制的阈值。此时,系统可以开始横向扩展。但是,如果新资源没有足够快地可用,则现有资源可能会耗尽,系统可能会失败。如前所述,为防止这种情况发生,系统会暂时受到限制。当自动缩放完成并且额外的资源可用时,可以放松限制。

问题和考虑


在决定如何实现此模式时,您应该考虑以下几点:

  • 限制应用程序和使用的策略是影响整个系统设计的架构决策。应该在应用程序设计过程的早期考虑节流,因为一旦实现了系统就不容易添加。
  • 必须快速执行节流。系统必须能够检测到活动的增加并做出相应的反应。系统还必须能够在负载减轻后迅速恢复到原始状态。这需要持续捕获和监控适当的性能数据。
  • 如果服务需要暂时拒绝用户请求,它应该返回特定的错误代码,以便客户端应用程序了解拒绝执行操作的原因是由于限制。客户端应用程序可以在重试请求之前等待一段时间。
  • 系统自动缩放时,节流可用作临时措施。在某些情况下,如果活动突然爆发并且预计不会长期存在,则最好简单地限制而不是扩展,因为扩展会大大增加运行成本。
  • 如果在系统自动缩放时将节流用作临时措施,并且如果资源需求增长非常快,则系统可能无法继续运行,即使在节流模式下运行也是如此。如果这不可接受,请考虑保持更大的容量储备并配置更积极的自动缩放。

何时使用此模式


使用此模式:

  • 确保系统继续满足服务水平协议。
  • 防止单个租户垄断应用程序提供的资源。
  • 处理活动的突发。
  • 通过限制保持系统运行所需的最大资源水平来帮助优化系统成本。

例子


最后一张图说明了如何在多租户系统中实现节流。每个租户组织的用户都可以访问云托管的应用程序,并在其中填写和提交调查。该应用程序包含监控这些用户向应用程序提交请求的速率的工具。

为了防止来自一个租户的用户影响应用程序对所有其他用户的响应能力和可用性,对来自任何一个租户的用户每秒可以提交的请求数施加了限制。应用程序阻止超过此限制的请求。

Figure 3 - Implementing throttling in a multi-tenant application

下一步


在实施此模式时,以下指南也可能是相关的:

  • 仪器仪表和遥测指导。限制取决于收集有关服务使用量的信息。描述如何生成和捕获自定义监控信息。
  • 服务计量指南。描述如何计量服务的使用,以了解它们的使用方式。此信息可用于确定如何限制服务。
  • 自动缩放指导。节流可用作系统自动缩放时的临时措施,或消除系统自动缩放的需要。包含有关自动缩放策略的信息。

相关指导


在实现此模式时,以下模式也可能是相关的:

  • 基于队列的负载均衡模式。基于队列的负载均衡是实现节流的常用机制。队列可以充当缓冲区,帮助平衡应用程序发送到服务的请求的速率。
  • 优先队列模式。系统可以使用优先队列作为其节流策略的一部分,以维持关键或更高价值应用程序的性能,同时降低不太重要的应用程序的性能。

原文:https://docs.microsoft.com/en-us/azure/architecture/patterns/throttling

本文:https://jiagoushi.pro/node/2166

SEO Title
MS Throttling pattern