Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【韧性架构设计】软件韧性:从意外中恢复的 7 个必备因素

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

作者头像
架构师研究会
发布于 2022-09-26 03:27:14
发布于 2022-09-26 03:27:14
1K00
代码可运行
举报
文章被收录于专栏:超级架构师超级架构师
运行总次数:0
代码可运行

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

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

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

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

目录

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

什么是软件弹性

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

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

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

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

弹性软件因素

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

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

让我们开始吧。

逐步推出/部署

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

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

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

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

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

重试软件弹性

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 调用在重试后仍然失败,您可以回退到响应的本地副本。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 等外部服务通信时。我希望这可以帮助您构建更具弹性的软件。如果您还有其他方面要分享,请不要忘记发表评论。

谢谢大家关注,转发,点赞和点在看。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 首席架构师智库 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【韧性架构设计】分布式系统的韧性
由许多协同工作的微服务组成的云原生应用程序架构形成了一个分布式系统。确保分布式系统可用——减少其停机时间——需要提高系统的弹性。弹性是使用提高可用性的策略。弹性策略的示例包括负载平衡、超时和自动重试、截止日期和断路器。
架构师研究会
2022/07/29
5030
【韧性架构设计】分布式系统的韧性
【韧性设计】韧性设计模式:重试、回退、超时、断路器
软件本身并不是目的:它支持您的业务流程并使客户满意。如果软件没有在生产中运行,它就无法产生价值。然而,生产性软件也必须是正确的、可靠的和可用的。
架构师研究会
2022/05/25
1.4K0
【韧性设计】韧性设计模式:重试、回退、超时、断路器
分布式系统的弹性设计
在讨论分布式系统的弹性之前,让我们快速回顾一些基本术语: 弹性Resiliency:任何系统从困难中恢复的能力,(banq注:弹性也就是适应能力)。 分布式系统:一些网络组件通过传递消息来完成一个共同目标。 可用性:任何系统在任何时间点保持正常运行的可能性。 故障与故障:故障Fault是您的系统中是不正确的内部状态。系统中一些常见的故障例子包括: 1.存储层缓慢 2.应用程序中的内存泄露 3.被阻塞的线程 4.依赖性故障 5.在系统中传播坏数据(通常是因为输入数据没有足够的验证) 失败Failure是系统无法执行其预期工作。 失败意味着系统正常运行时间和可用性的损失。故障如果不被封装,会导致在系统中传播,从而导致失败。 当故障Fault转为失败Failure时就意味着系统发生了故障: 弹性就是为了防止故障Fault转化为失败Failure 我们为什么关心系统的弹性? 系统的弹性与其正常运行时间和可用性成正比。系统越有弹性,服务用户的可用性越高。 如果不具有弹性能力,可能会以多种方式影响公司各个方面。 分布式系统的弹性设计很难 我们都明白'可用'至关重要。为了保证可用性,我们需要从零开始建立弹性,以便我们系统中的故障自动恢复。 但是在具有多个分布式系统的复杂微服务架构中建立弹性是很困难的。这些困难是: 1.网络不可靠 2.依赖性总是失败 3.用户行为是不可预测的 虽然构建弹性很难,但并非不可能。遵循一些构建分布式系统的模式可以帮助我们在整个服务中实现较高的正常运行时间。我们将讨论未来的一些模式: 模式[0] = nocode
lyb-geek
2018/09/27
2K0
分布式系统的弹性设计
[微服务架构 ]微服务集成中的3个常见缺陷 - 以及如何避免它们
微服务风靡一时。 他们有一个有趣的价值主张,即在与多个软件开发团队共同开发的同时,将软件快速推向市场。 因此,微服务是在扩展您的开发力量的同时保持高敏捷性和快速的开发速度。
架构师研究会
2019/05/06
1.2K0
[微服务架构 ]微服务集成中的3个常见缺陷 - 以及如何避免它们
【韧性架构】让你的微服务容错的 5 种模式
在本文中,我将介绍微服务中的容错以及如何实现它。如果你在维基百科上查找它,你会发现以下定义:
架构师研究会
2022/06/08
1K0
【韧性架构】让你的微服务容错的 5 种模式
【微服务架构】为故障设计微服务架构
微服务架构可以通过定义明确的服务边界隔离故障。但就像在每个分布式系统中一样,网络、硬件或应用程序级别问题的可能性更高。由于服务依赖关系,任何组件都可能对其消费者暂时不可用。为了最大限度地减少部分中断的影响,我们需要构建可以优雅地响应某些类型的中断的容错服务。
架构师研究会
2022/05/25
5110
【微服务架构】为故障设计微服务架构
【软件架构】支持大规模系统的设计模式和原则
今天,即使是小型初创公司也可能不得不处理数 TB 的数据或构建支持每分钟(甚至一秒钟!)数十万个事件的服务。所谓“规模”,通常是指系统应在短时间内处理的大量请求/数据/事件。
架构师研究会
2022/05/05
6150
【软件架构】支持大规模系统的设计模式和原则
故障驱动的微服务架构设计
此文背景: 之所以发布此文,是有一个直接的原因,就是我们之前在线上遇到了一个使用timeout来判断是否失败的案例,这是真实的,结果就是效果很不好。看了本文中介绍的各种技术和架构模式,让我忽然对之前的这个案例有了一个新的认识,就是“快速失败”不应该依赖于传统的比如timeout这种超时机制来进行,也许使用本文中介绍到的技术(比如:Circuit Breakers)要更加地可靠和受控。 目录 微服务架构的风险 优雅的服务降级 变更管理 健康检查和负载平衡 自愈(Self-healing) 故障转移缓存
ImportSource
2018/04/03
1.4K0
故障驱动的微服务架构设计
深入微服务核心:从架构设计到规模化
《Building Microservices》这本书是吃透微服务的大部头,本文基于全书内容,系统性地阐述了微服务架构的设计原则、实施策略与挑战,从微服务的核心概念出发,延伸到架构设计、服务拆分、集成技术及规模化实践,为开发者提供了构建稳健微服务体系的指导框架。
腾讯云开发者
2025/04/24
2990
深入微服务核心:从架构设计到规模化
业务开发:防御性编程之网络超时与重试机制、幂等机制的关系
网络超时的情况可以分为服务端超时和客户端超时。当api请求超时,客户端并不知道服务端是否成功处理请求,即网络请求超时,服务端业务执行结果可能是成功,也可能是失败。
崔认知
2023/06/19
3930
业务开发:防御性编程之网络超时与重试机制、幂等机制的关系
微服务架构中10个常用的设计模式
从软件开发早期(1960 年代)开始,应对大型软件系统中的复杂性一直是一项令人生畏的任务。多年来为了应对软件系统的复杂性,软件工程师和架构师们做了许多尝试:David Parnas 的模块化和封装 (1972), Edsger W. Dijkstra (1974)的关注点分离以及 SOA(1988)。
架构之家
2022/07/12
9740
微服务架构中10个常用的设计模式
与我一起学习微服务架构设计模式3—微服务架构中的进程间通信
选择合适的进程间通信机制是一个重要的架构决策,它会影响应用的可用性,甚至与事务管理相互影响。
java达人
2019/10/23
1.9K0
万字详解高可用架构设计
系统高可用是一个宏大的命题,从设计思想、架构原则到工程能力、服务管理等等方方面面,每个视角单拆出来都不是一篇文章可以解决的。本文将从大局上全面系统地梳理高可用系统架构,起到一个提纲挈领的作用。
腾讯云开发者
2025/01/07
2.3K0
万字详解高可用架构设计
构建故障恢复系统
作者 | Gandharv Srivastava 译者 | Sambodhi 策划 | marsxxl 1.5 亿,这个数字,是 Capillary 的 Engage+ 产品在新年高峰时段两小时内发送的通信量。即便是这样的小故障,也会影响到我们客户的资本和我们产品的信誉。 故障就像一场大爆炸,它们可以是手榴弹的爆炸,也可以是核弹级别的爆炸,而爆炸造成的破坏取决于爆炸半径。再好的系统,也会有出故障的一天。若不及早发现并加以处置,也会加剧造成更大的破坏。 请注意,这篇文章将着重于微服务设计中的健壮性和
深度学习与Python
2023/03/29
9090
构建故障恢复系统
微服务架构如何避免大规模故障?
点击关注公众号,Java干货及时送达 微服务架构通过一种良好的服务边界划分,能够有效地进行故障隔离。但就像其他分布式系统一样,在网络、硬件或者应用级别上容易出现问题的机率会更高。服务的依赖关系,导致在任何组件暂时不可用的情况下,就它们的消费者而言都是可以接受的。为了能够降低部分服务中断所带来的影响,我们需要构建一个容错服务,来优雅地应对特定类型的服务中断。 本文基于一些在RisingStack的顾问咨询与开发经验,介绍了如何运用一些最常用的技术和架构模型,去构建与维护一个高可用的微服务系统。 如果你不熟
Java技术栈
2022/03/03
4130
设计一个容错的微服务架构
本文介绍了构建和操作高可用性微服务系统的最常见技术和架构模式。如果你不熟悉本文中的模式,那并不一定意味着你做错了。系统设计没有通用解决方案,建立可靠的系统总是会带来额外的成本。
Superbeet
2020/04/17
7170
微服务架构及其最重要的10个设计模式
微服务架构,独享数据库、事件驱动、CQRS、Saga、BFF、API 网关、Strangler、断路器、外部化配置、消费端驱动的契约测试
深度学习与Python
2021/01/06
1.3K0
构建容错软件系统的艺术
我们生活在一个由软件系统驱动的世界。它们已融入我们的日常生活,其持续、可靠的性能不再是奢侈品,而是必需品。企业现在比以往任何时候都更需要确保其系统保持可用性、可靠性和弹性。这种必要性是由满足客户和超越竞争对手的愿望推动的。实现这一目标的秘诀是什么?构建容错软件系统。
用户5166556
2023/10/19
2640
构建容错软件系统的艺术
Istio如何同时实现Hytrix|Ribbon|Zuul|微服务安全的功能?:为微服务引入Istio服务网格(下)
版权说明:本文由高晓雪参照如下文档翻译。魏新宇根据高晓雪的翻译文档,做了适当的注解和文字矫正。 https://developers.redhat.com/download-manager/file/istio_mesh_for_microservices_r1.pdf 本文适合对istio的读者提供泛读参考,对istio理解较深的读者,建议直接阅读英文原文。本系列分上下两篇:上篇为1-3章内容,下篇为4-7章内容。 目录 为微服务引入Istio服务网格 1.介绍 1.1.更快的挑战 1.2.认识I
魏新宇
2018/06/25
2.2K0
重试暂时性故障处理设计-常用的架构设计原则
与远程服务和资源通信的所有应用程序必须对暂时性故障敏感。 对于云中运行的应用程序尤其如此,因为其环境的性质与通过 Internet 建立连接的特点,意味着更容易遇到这种类型的故障。 暂时性故障包括组件和服务瞬间断开网络连接、服务暂时不可用,或者当服务繁忙时出现超时。 这些故障通常可自我纠正,如果在适当的延迟后重复操作,则可能会成功。
jack.yang
2025/04/05
1050
推荐阅读
相关推荐
【韧性架构设计】分布式系统的韧性
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验