飙血推荐
  • HTML教程
  • MySQL教程
  • JavaScript基础教程
  • php入门教程
  • JavaScript正则表达式运用
  • Excel函数教程
  • UEditor使用文档
  • AngularJS教程
  • ThinkPHP5.0教程

快速失败的可靠软件策略:有效地调试故障

时间:2021-12-10  作者:匿名  

如果你没有听说过这个惊人的创新,它就是一个厨房机器人……嗯,它是一个神奇的超级烹饪机器。在设计 Thermomix 时,它的设计者采用了故障安全而不是快速故障的方法。在这种情况下,这是一个明智的选择,但它有其缺点。

例如,我的机器试图从故障中恢复,这导致它进入无限恢复循环。我真的无法从密封关闭的盖子中取出食物。但通常,它是我拥有的最可靠的设备之一。

我们应该采取哪种方法以及它如何影响我们的长期可靠性?

快速故障与故障安全方法

如果您不熟悉这些术语,快速失败意味着系统会在意外情况下迅速失败。即使输入错误,故障安全系统也会尝试恢复并继续。

Java 尝试采用快速失败的方法,而 JavaScript 更倾向于失败安全的方法。快速失败行为的一个很好的例子是它们各自的归零方法。在 Java 中,null 会产生 NullPointerException,它会立即且清晰地使代码失败。JavaScript 使用“未定义”,它可以在系统中传播。 

我们应该选择哪一个?

这很难说。研究很少,我想不出一种方法可以客观地应用科学方法来衡量这种方法论。它既有技术方面的,也有核心业务方面的。很难最终确定某些事情。我可以肯定的是,这不应该只是一个高级行政人员的决定。这是一种管理应与工程结合以减轻下行风险的政策。这适用于您,无论您是工程师还是商业领袖。无论您是硅谷初创公司、亚马逊还是银行。这些原则是普遍的。 

使用微服务的公司可能更致力于某种形式的故障安全。弹性是微服务的一个共同特征,它属于故障安全阵营。

现代故障安全方法试图通过使用阈值来限制故障来避免该方法的一些陷阱。一个很好的例子是基于物理和软件的断路器。断路器会断开出现故障的功能,因此不会产生级联故障。 

选择快速失败方法的公司会冒一些风险,但会获得一些丰厚的回报。当您选择这种方法时,如果错误进入生产环境,失败可能会很痛苦,但有两个显着优势:

  • 在开发/调试周期中更容易捕获快速失败系统中的错误

  • 这些错误通常更容易修复

快速失败方法可以更好地处理此类错误,因为级联效应的风险较低。故障安全环境可以尝试从错误中恢复并推迟它。因此,开发人员会在更晚的阶段看到错误,并且可能会错过错误的根本原因。

从历史上看,我更喜欢快速失败;我相信当我们进入生产阶段时,它会使系统更加稳定。但这是轶事,很难凭经验证明。我认为快速失败的系统需要有一定的风险偏好,无论是工程人员还是管理人员。高管们可能更是如此。

请注意,尽管有这种意见,我还是说 Thermomix 很聪明地选择了故障安全。Thermomix 是在未知且易变的环境中运行的硬件。这意味着在生产中修复几乎是不可能的,而且部署成本非常高。像这样的系统必须在最坏的情况下幸存下来。

我们需要从之前的失败中吸取教训。成功的公司同时使用这两种方法,因此很难选择最佳方法。

云中的混合环境

处理失败的一个更常见的“策略”是结合两个世界的最佳方面:

  • 调用本地代码或服务时快速失败,例如 DB

  • 依赖远程资源时的故障安全,例如远程 Web 服务

这个方向背后的核心假设是我们可以控制我们的本地环境并对其进行很好的测试。企业不能依赖云中的随机服务。他们可以通过避免外部风险但承担快速故障系统的计算风险来构建容错系统。

定义失败

在讨论失败时,我们将重点放在 500 个错误页面、崩溃等假设上。这些都是严重的 P1 失败。但它们绝不是唯一的故障类型,甚至不是最严重的故障类型……崩溃通常标志着一个问题,我们可以通过自动启动新的服务器实例来修复甚至解决问题。这其实是一个我们可以比较优雅地处理的失败。

一个更加险恶的失败是数据损坏。错误可能会导致不良数据进入数据库,并可能导致长期问题。甚至安全风险和崩溃也可能因数据损坏而导致,而这些将更难修复。快速故障系统有时可以将此类问题扼杀在萌芽状态。 

对于云计算,我们看到诸如断路器、重试等防御性编程的兴起。这是不可避免的,因为这背后的假设是云中的一切都可能失败。我们需要发展关于我们可以预期的失败的核心知识。我发现有用的一种方法是查看来自长时间运行的集成测试(夜间测试)的日志。

一个好的 QA 流程的一个重要部分是长时间运行的测试,这些测试需要花费数小时来运行并对系统施加压力。在查看这些测试的日志时,我们有时会注意到问题并未失败,但与我们对系统的假设相冲突。这可以帮助找到所经历的阴险错误。

不要修复错误

不是马上。好吧,除非它在生产中,显然......

在修复错误之前,我们应该了解它们。为什么测试过程没有发现呢?它是级联效应还是缺少测试覆盖率?我们怎么错过了?

当开发人员解决错误时,他们应该能够在问题跟踪器上回答该问题。然后是难题,找到失败的根本原因并修复流程,以免此类问题再次发生。这显然是处理每个错误的极端方法,因此我们在选择要关注的错误时需要谨慎行事。但这必须始终适用于生产中的错误。我们必须彻底调查生产中的错误,因为云中的故障可能会给业务带来很大的问题,尤其是在经历指数增长时。

调试失败

现在我们对这个主题有了一个大致的了解,让我们进入一个专注于调试的博客的更实用的方面。这里没有什么特别的创新。调试一个快速失败的系统非常容易。

但是我们可以使用一些陷阱、提示和技巧来促进快速失败。我们还可以使用其他策略来调试故障安全系统。

确保我们快速失败

使用以下策略:

  • 抛出异常 - 在文档中定义每个 API 的契约,如果 API 被调用时带有越界状态、值等,则立即失败。

  • 通过单元测试强制执行此策略 - 仔细检查每个 API 文档中的每一条语句。编写一个强制执行该行为的测试

  • 如果您依赖外部资源,请针对不可用情况、低性能和突然不可用创建测试

  • 定义低超时,从不重试

核心思想是快速失败。假设我们需要调用 Amazon Web 服务。网络问题可能会引发故障。快速故障系统将预期失败并向用户呈现错误。

故障安全的智能故障

核心思想与其说是避免失败,不如说是不可避免。核心思想是减轻失败的打击。例如,如果我们采用上面的 Amazon Web 服务示例... 故障安全环境可以缓存来自 Amazon 的响应并尝试显示较旧的响应。 

这里的问题是用户可能会获得过时的信息,这可能会导致级联效应。这可能意味着我们需要更长的时间才能找到问题并修复它,因为系统可能看起来很正常。

这里明显的提示是记录每个故障和缓解措施并发出警报,以便我们可以解决它们。但是还有另一种不常见但可能对某些人感兴趣的混合方法。

混合故障安全

混合故障安全环境从快速故障环境开始。对于测试环境和暂存也是如此。核心创新是封装单个组件并提供故障安全层的包装器。这可能与 Cloudflare 或 Amazon cloud front 提供网站的缓存版本非常相似。  

但是我们如何将其应用到代码或 OPS 层中呢?

当系统接近生产时,我们需要检查系统内部的故障点,重点关注外部依赖,也关注内部组件。 

像上面的 Amazon 示例这样的简单示例将默认包含快速失败。故障安全包装器可以重试操作并可以实施各种策略。有一些现成的软件工具可以让我们事后定义故障安全策略,例如故障安全、弹簧重试和许多其他此类工具。其中一些工具处于 SaaS API 级别,可以缓解可用性/网络问题。

这样做的缺点是添加了开发和 QA 中大多缺少的生产组件。但它包含了快速失败的许多优点,并使代码保持相对干净。

所有人的其他最佳实践

无论您选择哪种策略,以下是一些您应该牢记的最佳实践:

  • 在打开异常断点的情况下在调试器中运行软件。从断点中排除使用异常来控制流的 API(呃,请修复这些 API)。这让您可以挑战您对应用程序可靠性的假设

  • 确保环境是随机的。如果您使用本机代码,请随机化内存位置。始终随机化测试执行以促进失败

  • 正确的代码审查 - 我再怎么强调也不为过。我喜欢代码审查。我鄙视吹毛求疵!当我收到关于变量命名、代码样式等的响应时,它会按下我的按钮……有时这样的评论会忽略实际的错误。人们讨厌代码审查,因为这种挑剔。公司应在实质性流程和评估方面对开发人员进行培训。

概括

失败可以有多种形式和形式,我们应该接受失败的发生。尽管亚马逊、Facebook 和谷歌竭尽全力避免它,但它还是发生了。我们需要决定一个策略。进行假设并从整个工程过程中获得高级管理人员的支持。

我们需要做出选择:

  • 我们是否更频繁地失败并迅速恢复?

  • 我们是否很少失败但需要时间来恢复?

软件可靠性仍然是 QA/测试的一个功能。但归根结底,失败是不可避免的,我们需要做出战略选择。我相信大多数初创公司都应该专注于快速失败,因为成长心态使得保持失败安全策略的功能变得非常困难。由于我们有 QA 和测试,大多数这些问题都是异常值,很难优化。

湘ICP备14001474号-3  投诉建议:234161800@qq.com   部分内容来源于网络,如有侵权,请联系删除。