快速失败与鲁棒性

20
我们的产品是一个分布式系统。我所负责的模块相当新,非常严谨,并且经过了充分的测试。它们是以最新的最佳实践为基础开发的。其他模块可以被视为遗留软件。
虽然我对我负责的模块内发生的事情非常警惕,但我不断面临着要处理来自其他模块的错误数据的压力。本质上,我是一个“失败快速”原则的开发者,因此,当问题出现时,我通常能够消除我的模块中存在的错误可能性。这并不是为了指责别人,仅仅是为了节省浪费在错误地方查找错误的努力。
但是,我经常遇到的论点是:“我们不能让这些东西在生产环境中失败,客户希望这个工作,为什么你不解决这个问题。” 这将是一种强壮性的论点:在接受方面要宽松,在发送方面要保守。
我还应该注意到,这些大多数是间歇性问题。我们在集成测试中看到它们,但很难重现。时间和并发性都涉及其中。
我在两个原则之间很难取得平衡。部分原因是我担心如果我开始允许和传播异常数据,我会招惹麻烦,并且我对我的系统的信心不会那么强。但是,即使其他模块向我发送错误数据,我也不能反对保持系统正常工作。其他模块没有得到修复的原因是它们太复杂和脆弱了,而我的模块看起来仍然清晰而安全。但是,如果我不抵制这种压力,我的模块将逐渐被同样的问题所困扰,直到现在为止我一直在拒绝的那些问题。
我应该说,系统并没有在生产环境中“崩溃”,但我的模块可能只是向操作员显示一个错误,并要求他们联系支持人员。如果发生崩溃,那将是一个大问题,但如果我清楚地报告错误,那么这难道不是正确的做法吗?我怀疑我的同事只是不希望客户看到任何问题。但是我的模块正在拒绝我们产品内其他模块的数据,而不是客户输入。因此,我认为我们只是没有解决问题。
那么,我需要更加务实还是坚持自己的立场呢?
8个回答

4

我倡导“快速失败”的原则。不要把这看成是一种原则上的冲突,它更多是一种理解上的冲突。你的伙伴有一个不言而喻的要求(“不要让用户体验糟糕”),这意味着有一些遗漏的需求。你没有机会事先思考/实现这个需求,因此这个需求留下了令人不满的印象。忘记这个观点,重新以一个你可以应对的固定要求来处理这个问题。

也许最好的结果就是像你展示的那样给出一个错误信息。但听起来你在获得伙伴的支持之前就实现了它,当他们有权选择时。较早地沟通关于你正在做什么的内容可能会解决这样的事情。

小心避免想法的冲突。不断提到其他系统“过于复杂和脆弱”可能会引起人们的反感。简单地表达这些系统对你来说是新的,需要更长时间来理解。确保花费时间去理解,这样你才不会降低人们对你的能力的期望。


关于“未显示失败”的“缺失需求”的好观察。幸运的是,我们只在集成测试中看到了这种情况,这不是预期的错误,例如奇怪的并发/时间问题,但由于数据处理严谨,它立即标记出了问题。对于我们来说,审视问题并从中决定如何处理是至关重要的。只有看到这些错误,我们才得出结论,我们有一个并发问题。 - tolak

3
我认为这取决于如果你不停下来会发生什么。是否会出错处理某人的薪水?是否会发送错误的订单?那就值得停下来。
如果可能,两全其美-不要向用户报告错误,让客户同意发送诊断报告并报告每次故障。麻烦拥有故障模块的开发人员修复它们。通过麻烦我是指对他们提出错误报告。或者,如果管理层认为修复成本不值得,则不要修复。
我还会编写针对这些失败模块的单元测试,特别是如果您可以确定导致它们生成错误输出的原始输入是什么。
然而,真正重要的是审核您的表现的人希望您做什么,特别是在您通过电子邮件向他们解释问题之后。

3
我不想深入解释原因,但你是正确的。
根据我的经验,PHB(指高层管理人员)缺乏理解快速失败有价值的部分大脑,以及“做任何必要的事情,即使需要吃亏也要保持稳健”的定义是一个坏主意。这是没有希望的。他们只是没有硬件来理解它。他们往往会说一些“好的,你说得有道理,但用户怎么办”的话 - 这只是他们版本的考虑孩子们,每次提到这个话题都意味着和我谈话结束了。
我的建议是要坚定立场。永远如此。

那么我们开发软件,不考虑用户想要或需要什么吗?额,不是的,(-1)。 - DanSingerman
4
@Dan,我不想深入讨论的核心,但如果你不知道-主张快速失败的人正在考虑用户的需求; 如果您快速失败,则可以轻松地识别出真正的错误(而不是用“健壮性”来隐藏它),从而更好地满足用户的需求。 这是大多数PHB所忽视的要点。 - Terry Mahaffey

2
简单来说,这听起来像是“不要检查你处理不了的东西”。你能捕获错误并报告它意味着你没有传播它。但这也意味着由于你可以报告它,你有一些机制来捕获错误,并且因此有可能自己处理和纠正它,而不是仅仅报告它。
注意,我假设你的错误报告比你在系统深处捕获的随机异常更有趣。但即使是这样,如果这是一个你正在测试并创建的异常(例如,你检查分母是否为零并发送错误,而不是无意中除以零并在更高层次上捕获异常),那么这表明你很可能有一种解决问题的方法。
底线是,你需要两者。你需要尽量使数据无误,但也要报告意外情况。
我认为你不能锁门,双臂交叉地说“这不是我的问题”。它来自“旧的、脆弱的系统”这一事实是没有意义的。你的代码不是旧的和脆弱的,显然,在整个集成系统中,“修复”数据的有效位置是你的代码。是的,旧模块将继续向其他较小的系统提供GIGO,但这些遗留模块与你的新模块结合起来是一个有机的整体,因此组成了“系统”。
这里的典型实际问题仅仅是编写所有这些修复代码与新功能之间的时间/价值方程。这是一个不同的辩论。但如果你有时间,并且你知道可以清理传入数据的事情,“在接受什么方面要慷慨”是明智的策略。

感谢您提供平衡和深思熟虑的回复。它帮助我明确了问题。 - tolak

1
感谢大家。引发这个问题的案例已经圆满解决,部分得益于我从上面的答案中获得的见解。
我的最初反应是坚持快速失败,但我考虑了一些更多的事情,并得出结论,我的模块的一个作用是为系统的其余部分提供稳定的锚定点。这并不一定意味着接受错误数据,而是将问题暴露出来,在透明的方式下隔离它们并处理它们,直到我们找到解决方案。
我计划添加一个新的处理程序和代码路径,以便正确执行此案例,就好像它是先前未记录的特殊用例一样。
我们进行了讨论,我重申了在边界处处理问题的必要性,但也愿意提供帮助。我向对方概述了我的计划,因为我怀疑我的立场被视为过于迂腐,解决方案被认为只是让我关闭无关紧要数据的验证,即使它是不正确的。然而,实际上,我工作的方式在很大程度上是数据驱动的,所以我解释了为什么它必须是正确的,以及行为如何受其驱动,以及如何在容纳这些数据时我将实现一个特殊的代码路径。

我认为这加强了我的立场,并导致对另一方修复数据的厌恶进行了更彻底的讨论。结果证明,这更多是由于处理容易出错的遗留系统而不是实际障碍所导致的疲惫感。有一个相对简单的解决方案,只是改变现状令人害怕,这是一种相当根深蒂固的心态。

但是,在阐述所有挑战和可能的解决方案后,我们最终同意修复数据,到目前为止,似乎已经解决了我们的问题。我们的集成测试现在始终通过,但我们还添加了日志记录,并将继续监视。

总之,我认为对我来说,两个原则的综合是快速失败对于暴露问题至关重要。但是一旦它们浮出水面,健壮性意味着提供透明的路径以在不损害系统的情况下继续操作。我能够提供这样的方案,并通过这样做赢得了另一方的好意,并最终修复了数据。

再次感谢所有回复的人。我太新了无法评价评论,但我确实欣赏所提出的所有观点。


哇,整个帖子,包括评论和答案,都非常专业和深思熟虑。没有膝跳反应,没有指责,也没有抱怨。我对参与讨论的每个人印象深刻。点赞为提供结论而奖励——尽管对接受自己的答案有些犹豫。 - MJB
我对答案应该怎么办并不确定。我认为那是应该采取的行动方案。我还在学习如何操作这个。 - tolak

0
这是一个棘手的问题。如果你的模块接收到错误数据,但对你来说只要不做任何处理并返回结果就可以了,那我建议将错误写入错误日志而不是向用户显示错误信息。

0

这有点取决于您所遇到的错误类型。如果系统故障的方式意味着您可以继续进行而不向系统的任何其他部分提供错误数据,则应尽一切可能使用给定的任何输入。

然而,对我来说,数据纯度胜过工作系统,您不能允许错误数据传播到其他地方并损坏其他系统。在您可以将数据调整为正确状态并继续运行的程度上,您应该这样做,理论上数据是安全的,您必须保持系统运行......

我喜欢用数据流的术语来思考问题。传递错误数据会污染整个数据流,这很糟糕,因为就像真正的污染一滴就能破坏整个数据流(如果有一个元素出错,您还能相信什么?)。但同样糟糕的是阻止流动,让没有通过的东西通过,因为您发现了一些可以轻松删除的内容。将其过滤掉,如果每个阶段的每个人都进行过滤,则即使在中间出现了一些杂质,也可以从另一端得到清晰干净的数据。


0
你的同行问道:“为什么你不解决这个问题呢?”
你说,你可以检测到错误数据,并向用户报告错误。这是正常的做法——一旦你知道传递给函数的数据有问题,你应该快速失败(这也是我在这里阅读其他答案时得出的建议)。
然而,你的问题没有指定你的软件运行的领域。如果你知道传入的数据是错误的,你是否可以请求再次获取数据?实际上能够从这种情况中恢复吗?
我提到了“领域”在这里很重要。所以,如果你有一个应用程序,例如显示流媒体视频数据,可能你的无线信号很弱,因此流媒体数据损坏了,系统应该“快速失败”并显示错误消息吗?还是应该显示质量较差的图像,并根据问题的严重程度尝试重新连接?
根据你的领域,你可能可以检测到错误数据,并在不影响用户的情况下再次请求数据。(这显然只适用于你期望第二次数据更好的情况,但你确实说你遇到的问题是间歇性的和可能与并发相关的)...

所以,快速失败是好的,并且如果你无法恢复,绝对应该这样做。而且你绝对不应该传播错误的数据。但是,在某些领域中你可以恢复,如果你能够恢复,那么直接失败并不一定是最好的选择。


这是一个关键系统,但它只是对人类操作员的指导。它不能告诉一个已经执行了某些简单操作的操作员,由于一些内部问题,他必须停止。我可以理解在用户表现正确但系统失败的生产中暴露问题的不情愿。 - tolak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接