我们应该设计程序来随机杀死自己吗?[关闭]


76

简而言之,为了整个系统的利益,我们是否应该将死亡设计在较低的程序,进程和线程中?

失败发生。进程死亡。我们计划灾难,并偶尔从灾难中恢复。但是我们很少设计和实现无法预测的程序终止。我们希望我们的服务正常运行时间只要我们愿意保持它们正常运行即可。

Netflix的Chaos Monkey是该概念的一个宏观示例,它在某些情况下会随机终止AWS实例。他们声称这有助于他们发现问题并构建更多的冗余系统。

我在说的是较低的水平。这个想法是让传统上长时间运行的进程随机退出。这将迫使冗余进入设计并最终产生更具弹性的系统。

这个概念已经有名字了吗?它已经在行业中使用了吗?

编辑

根据评论和答案,恐怕我不清楚我的问题。为了清楚起见:

  • 是的,我的意思是随机的,
  • 是的,我的意思是在生产中,并且
  • 不,不仅用于测试。

解释一下,我想比喻多细胞生物。

在自然界中,生物由许多细胞组成。这些单元自行分叉以创建冗余,然后最终死亡。但是,应始终有足够种类的正确细胞供生物体发挥功能。这种高度冗余的系统还有助于在受伤时进行康复。细胞死亡,生物体得以生存。

将随机死亡纳入程序中将迫使更大的系统采用冗余策略以保持生存。这些相同的策略是否可以在遇到其他无法预测的故障时使系统保持稳定?

而且,如果有人尝试过这种方法,那叫什么呢?如果它已经存在,我想了解更多。


13
我没有任何有用的答案作为答案,但这绝对是一个有趣的问题。如果由组件本身的性质来保证随机组件故障,那么肯定会迫使程序员编写一个像样的组件体系结构(正确)以应对随机组件故障。
汤姆W

1
如果我理解正确,则可能有点相关: en.wikipedia.org/wiki/Mutation_testing。虽然变异测试有助于加强测试,但我认为您正在寻找一种基于随机性的方法来加强代码。
MetaFight 2013年

10
实际上,这个概念与计算一样古老,它在每个程序中都被使用,当然它有一个名称:它被称为:bugs
mouviciel 2013年

3
如果您不通过不可靠的网络对其进行测试,则不会调用经过测试的通信协议实施,因为您的设备是可靠的,因此必须对其进行模拟。
卡兹(Kaz)2013年

5
微软已经尝试了一段时间,他们用代号“ Windows”来称呼它。如果它产生了更好的策略,则值得商...……它可能只是降低了期望值。

Answers:


60

没有。

我们应该设计适当的错误路径处理,并设计测试用例(以及其他过程改进),以验证程序可以很好地处理这些异常情况。像混沌猴子的东西可以成为其中的一部分,但只要你做“必须随机崩溃”一要求,实际随机崩溃成为事物的测试员无法文件作为错误。


10
谢谢@Telastyn。我认为,坠机的原因可能是这里的原因。有目的的死亡崩溃可能会产生副作用(日志,错误代码,信号),从而将其与代码故障区分开。
jimbo 2013年

1
即使它有助于发现弱点,也并不意味着它是可行的。重复的风险(可能性和后果程度)是决定您是否对该Bug进行任何操作以减轻将来发生的可能性的重要因素。它是高风险系统的长期价值工具。
JustinC

这个想法是,即使子组件随机崩溃,用户也不会注意到。因此,当测试人员报告他们可以看到随机崩溃之一时,这意味着无法捕获子组件崩溃,这将是一个可归档的错误。
菲利普

1
实际上提出的是对不良路径处理的现场测试。许多部署(例如Netflix的例子)都需要进行实际的负载测试,这在许多情况下仅在实际部署中才可行。程序日志崩溃很容易通过明显的日志记录进行检测-有趣的是附带损害和对相关系统的影响。
ctpenrose

1
您可以实现一个智能的随机崩溃程序(例如Chaos Monkey),它可以让您知道程序何时随机崩溃。这样,您就知道何时遇到了合法崩溃,以及何时是稳定性测试崩溃。
Zain R

19

在软件或硬件中引入缺陷以测试容错机制的过程称为故障注入

从维基百科:

故障注入技术的历史可以追溯到1970年代,当时它首次用于在硬件级别引发故障。这种类型的故障注入称为“硬件实现的故障注入(HWIFI)”,它试图模拟系统内的硬件故障。硬件故障注入的第一个实验仅涉及短路电路板上的连接并观察对系统的影响(桥接故障)。它主要用于测试硬件系统的可靠性。后来开发了专门的硬件来扩展该技术,例如用强辐射轰击电路板特定区域的设备。很快发现,故障可能是由软件技术引起的,并且该技术的各个方面对于评估软件系统可能很有用。


+适合作为第二级压力测试。在人为的压力测试通过[达到令人满意的程度]之后,请插入一些随机性以确保意外的环境变化不会造成灾难性的影响。当失败是高风险(可能性或后果严重性)时,这可能很有价值。我不会部署到生活,直到我在实验室环境中非常有信心,然后只对增量部分我是最有信心英寸
JustinC

9

是。不会吧

定期终止是一把两刃剑。您将被一条边缘或另一条边缘击中,而这两种危害中的较小者则取决于您的情况。

可靠性是优势之一:如果您强迫程序随机(或可预测地)有序地结束,则可以为该事件做好准备并进行处理。您可以保证该过程在不忙于执行有用的操作时会退出。这也保证了在经过批准的运行时间后仍将表现出来的错误不会在生产中引起他们的丑陋头脑,这是一件好事。Apache HTTPD的设置可让您调整终止前子进程(或更新版本中的线程)将处理的请求数量。

另一个优势是可靠性:如果您不允许程序长时间运行,您将永远找不到随时间推移而显现出来的错误。当您最终遇到这些错误之一时,很可能导致程序返回错误答案或根本无法返回答案。更糟糕的是,如果您运行同一任务的多个线程,则由时间或计数引起的错误可能一次影响非常大量的任务,并导致凌晨3点进入办公室。

在运行许多相同线程的环境中(例如,在Web服务器上),实际的解决方案是采用混合方法,以确保可接受的故障率。如果您运行100个线程,则以99:1的长短比率运行意味着,只有一个会出现长期的错误,而其他线程会继续执行其所做的任何事情而不会失败。与之相比,如果100%长运行,则所有线程同时失败的风险要高得多。

在只有一个线程的情况下,最好让它运行并失败,因为重新启动过程中的停滞时间可能会导致不希望的延迟,而在实际工作中,延迟会成功完成。

无论哪种情况,重要的是要有一些监督过程,以便可以立即重新启动它们。而且,没有法律说您必须初步确定有关流程应运行多长时间的决定。收集操作数据将帮助您调整系统,以将故障保持在可接受的水平。

我建议不要执行随机终止,因为这样会使确定与时间相关的错误更加困难。Chaos Monkey这样做是为了确保管理软件正常工作,这是一个稍有不同的问题。


如果您在随机的时间间隔内终止该过程,该时间间隔延伸到无穷远,那么某些过程将永远存在。因此,我认为随机杀死进程与检测长期存在的进程不兼容。
Joeri Sebrechts

9

你真的是说随机吗?让软件随机杀死自己听起来像一个可怕的主意。那有什么用?

我猜您的意思是,对于长时间运行的线程/进程,我们应该保持现实,并接受它们运行的​​时间越长,它们越有可能遇到某种隐藏的错误,并陷入无法正常运行的状态州。因此,作为一种纯粹的务实措施,应该限制进程和线程的寿命。

我相信在90年代后期,Apache Web服务器使用了类似的东西。他们有一个工作进程池(不是线程),每个工作进程在固定的生存期后将被杀死。这可以防止服务器被陷入某些病理状态的工作进程所垄断。

我已经在该地区工作了一段时间,所以我不知道是否仍然如此。


6
IIS在管理UI中内置了定期重新启动功能,并且默认情况下启用了它。还有内存和CPU限制触发器,但是基于时间的触发器总是让我感到奇怪。
Mark Brackett

3
到目前为止,YouTube解决python内存泄漏的方法是重新启动该过程。
Xavi 2013年

3
我不认为OP会要求为了使程序恢复到正常运行状态而要终止程序,而是要终止程序以测试系统处理其死亡的能力以及程序的任何后续执行来处理程序。遗迹。
mowwwalker 2013年

1
@MarkBrackett不幸的是,定期重启似乎通过使程序员随便处理不良代码而达到了相反的目的。如果由错误代码引起的问题使您难以解决,那么编写错误代码的可能性就较小。
安东尼

+1。随机是坏的。根据定义,您无法预测其行为。即使您出于一次又一次关闭程序的目的将其放在此处,也可能是它根本没有完成,只是因为它是随机的,因此破坏了从那里开始的目的。对于程序员和试图销售该特定功能的营销人员来说,使流程在可预见的时间内关闭可能会更容易。“是的,没错。它在随机的时刻关闭!不,这是功能!您好?您好?!”
2013年

7

我看到的问题是,如果这样的程序死了,我们只会说“哦,这只是另一个随机终止-不用担心”。但是,如果有真正的问题需要解决怎么办?它将被忽略。

程序已经“随机地”失败,这是由于开发人员做出了神秘的决定,将其引入生产系统的错误,硬件故障等。当发生这种情况时,我们想知道这一点,以便我们进行修复。将死亡设计成程序只会增加失败的可能性,只会迫使我们增加冗余,这会花费金钱。

在测试冗余系统(这应该比实际发生的更多)时,在测试环境中随机杀死进程没有任何错,但在生产环境中却没有。我们是否会每隔几天从现场生产系统中拉出几个硬盘驱动器,还是在载满乘客的飞机上停用其中一台计算机?在测试场景中-很好。在现场制作场景中-我宁愿不这样做。


如果要实现随机终止,则肯定会打印一条日志消息“现在我正在终止”,这样您就可以区分故意的随机终止与错误。;-)而且,偶尔重新启动几个进程之一将不需要更多的冗余,因为无论如何您都应该这样做。
汉斯·彼得·斯托尔2013年

4

无需向应用程序添加随机退出代码。测试人员可以编写脚本,这些脚本会随机终止应用程序的进程。

在联网中,为了测试协议的实现,有必要模拟一个不可靠的网络。这没有内置到协议中。可以在设备驱动程序级别或某些外部硬件上对其进行仿真。

不要为外部可以实现的情况添加测试代码。

如果这是用于生产,那么我简直不敢相信!

首先,除非流程突然退出,以免进行中的交易和易失的数据丢失,否则这不是诚实地实现这一概念。即使是随机定时,计划的,优雅的退出也无法充分帮助架构准备以应对不是优雅的实际崩溃。

如果在应用程序中内置了真实的或现实的故障,则可能会像实际的故障一样导致经济损失,并且故意地有目的的经济损害从本质上讲基本上是一种犯罪行为

您可能可以摆脱许可协议中的条款,该条款免于因软件操作而引起的任何损害承担民事责任,但是,如果这些损害是故意造成的,则您可能无法放弃刑事责任。

甚至不要考虑这样的特技:使其尽可能可靠地工作,并且将假故障场景仅放入特殊的构建或配置中。


这应该是IMO接受的答案。SRP在这里适用。
user408866 2013年

不幸的是,我并不是仅仅为了测试。我将扩展问题进行解释。
jimbo

如果做得对,这些随机(而不是优美!)崩溃根本不会造成持久的危害。关键是:随着时间的流逝,您可以清除所有发生伤害的极端情况;其中一些您将永远不会在测试机上看到。如果有时发生真正的崩溃,您也将没有任何麻烦。我从没有尝试过,但是在某些情况下对我来说似乎很明智。当然,这是后话这就需要将应用程序的正式功能,而不是发展的东西偷偷英寸
汉斯-彼得·斯托

3

您可能想在容错的分布式系统中搜索“ 主动恢复 ”和“ 恢复活力 ”,以处理任意故障(即,不仅崩溃的进程,而且损坏的数据以及潜在的恶意行为)。关于重新启动进程(抽象意义上,实际上可能是VM或主机)的频率和条件应进行大量研究。直观地,您可以理解该方法的优势,因为它更喜欢处理一个死进程而不是叛徒进程...


2

这实际上与测试没有什么不同。如果您正在设计一个始终可用的故障转移解决方案(例如Netflix),那么可以-您应该对其进行测试。我不知道在整个代码库中散布随机退出是否是测试它的合适方法。除非您真的打算测试您的设计是否可以适应脚下的射击,否则似乎更合适的方法是通过操纵代码周围的环境并验证其性能来进行测试。

如果您不是在设计冗余系统,那么请否-不应添加该功能,因为您添加了一些随机出口。您只需要删除随机出口,就不会有问题。您的环境仍然可能对您造成故障,这时您可以将其归类为不受支持/无法修复,或者针对该故障加强代码并为此进行测试。经常这样做,您将意识到实际上是在设计冗余系统-请参阅场景1。

在某个时候,您可能会确定自己不再确定要处理或不处理哪些故障。现在,您可以开始随机拉出地毯以检测故障点。

关于Netflix示例的唯一有趣的事情是,它们在生产中运行这些测试。这在某种意义上是合理的-有些错误实际上是仅在生产环境中很难或不可能模拟的东西。我怀疑Netflix在测试环境中花了很长时间才适应生产环境。实际上,他们所做的只是试图在工作时间内发生崩溃,这对他们的市场有一定意义,但对其他许多市场而言却不是。


2

您要寻找的字词是最近由Nassim Nicholas Taleb提出的:抗脆弱性。绝对推荐他的书《抗脆弱》。它几乎没有提到IT,但最明显的相似之处是最令人鼓舞的。他的想法是将脆弱的<->健壮的范围扩展到脆弱的<->健壮的<->抗脆弱性。具有随机事件的脆弱中断,具有随机事件的鲁棒管理以及具有随机事件的抗脆弱收益。


1

这取决于。我注意到,程序员倾向于过于笼统地适用于其特定领域的技术,而忽略了所有其他技术。例如,以修复所有错误为代价来发布程序可能是个好办法……除非您对飞机控制器,核反应堆等进行编程。没有必要“不要优化-程序员的成本更高,那么运行程序的成本”对HPC有效,因为相对简单的程序可能会占用群集数月之久(甚至是大量用户使用的流行程序)。因此,即使X公司出于很好的理由而做Y,您也不必跟随他们的脚步,因为您的情况可能有所不同。

通常,错误处理例程是代码中测试最差的部分-尽管看起来很简单,但很难模拟内存不足或不存在某些重要文件。因此,我阅读了为Unix内核建议的使某些系统调用随机失败的文本。但是,这将使编写简单的程序变得更加困难(如果我不想麻烦处理错误,如果我需要将3个C ++库插入一起以在2个文件上运行程序)。即使有例外,GC也需要确保您保持一致的状态(在将节点添加到链接列表的中间想象一个例外)。

您拥有的分布式服务越多,失败的问题就越是“多久”,“如果”或“何时”的问题。据我所知,在数据中心中,RAID磁盘更换是日常操作的一部分-并非意外故障。如果您进行大规模操作,则即使一个组件发生故障的可能性很小,也需要考虑到这一点,否则很有可能发生某些故障。

我不知道您在做什么,但要知道它是否值得,您需要考虑一下是否需要考虑失败(忽略成本)或分析成本太高(考虑错误)考虑到成本开发时间)。


“程序员倾向于过分概括适用于其特定领域的技术”,我想在这句话中加框并挂在墙上。确实如此,不仅是软件,而且是整个生活。
Mark E. Haase 2013年

1

IIS服务器具有可配置的功能,该功能可以在工作进程使用了​​一定数量的内存之后或为一定数量的请求提供服务之后或在指定的时间范围内处于活动状态后自动回收工作进程。(http://msdn.microsoft.com/en-us/library/ms525803(v=vs.90).aspx)和(http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/ 1652e79e-21f9-4e89-bc4b-c13f894a0cfe.mspx?mfr = true

当像IIS这样的CONTAINER做到这一点时,保护服务器免受恶意进程的侵害是很有意义的。但是,我宁愿将此功能保持关闭状态,因为如果您已经对代码进行了充分的测试,则没有任何意义。

我们已经在不可靠的层(硬件,网络)上工作,所以我永远不会写任何有意随机杀死其线程或进程的代码。从经济的角度来看,随机杀死也是一个坏主意-如果有人认为我已将其编程为随机崩溃,则没人会使用我的API。最后,如果我要使用一个API或使用一个随机崩溃的线程的系统,我将不得不花很多钱为它创建一个足够强大的监视机制,以便我晚上可以安然入睡。

相反,如果我正在开发系统或API,我会编写脚本或使用一种工具来纯粹进行压力测试系统的弹性。我会在所有构建中进行这样的测试,以识别不良构建。但是,尽管这是一个必要的测试,但它永远不可能是一个“足够的”测试。


1

有一种与此想法相关的文献,它称为“仅崩溃”软件(也称为“面向恢复的计算”),您可以从Candea&Fox从2003年开始撰写的usenix论文开始。曾经通过杀死它们来停止程序,因此只有一个kill开关作为关闭按钮,以及一个锻炼得很好的恢复启动路径。

虽然我不确定这个想法的流行程度,但是某些特定技术确实有用。例如,不信任您的软件能够在请求时关闭自身,因此使用专门的监督程序(例如,监督程序等),还仔细考虑了哪些程序状态必不可少,并确保在适当的时候将其记录在设计的数据存储中。启用恢复(例如sql数据库)。


2
链接过时。如果您在答案中总结了仅崩溃的软件的要点,您的答案将会更强。

1

确实是随机的,不。但是,对于长时间运行的进程/线程,以给定的时间间隔或在闲置给定的时间(但取决于某些条件)之后或执行特定类型的任务之后,退出/重新启动可能是一个好主意。长时间运行的进程不可避免地会建立状态,包括陈旧的事物,它们可能会挂在内存上,从而阻止交换空间被释放,所有这些在退出时都会被清除(或应该被清除),从而提高了总体系统的稳定性。


1

这取决于您正在设计的应用程序类型。

随机崩溃是测试和提高分布式(网络)系统的鲁棒性的好方法。

在Netflix示例中,当您的程序依赖于远程服务时,该服务可能会由于各种原因而无法控制,这些原因是您无法控制的(硬盘坏了,断电,流星坠入数据中心等)。您的服务仍需要以某种方式保持运行。

你是怎样做的?添加冗余和扩展是常见的解决方案。

例如,如果鼠标咬着服务器的电源线,则您的服务应具有某种解决方案以保持运行。例如,它可以保留将要开始使用的冗余备份服务器。

但是,如果您的程序是无法在网络中运行的单进程应用程序,那么杀死它本身不会测试任何东西,因为无法从中恢复。

这是有关“混沌猴子”概念的一些额外评论, 网址为http://www.codinghorror.com/blog/2011/04/working-with-the-chaos-monkey.html


1

由于宇宙辐射,可能发生随机的位翻转。认识到此问题,并开发了各种技术来防止发生位翻转。

但是,不可能100%修复它,并且内存损坏仍然会引起问题,并且这些问题仍在发生(可能性很小)。

现在回答您的问题。是否需要设计一个非常强大的系统,取决于您在做什么。如果您需要制造太空飞船,则最好使其具有超强的耐用性,然后需要考虑到每个可能的问题。

如果需要设计普通的桌面应用程序,则应将随机崩溃视为代码中的错误。


0

这似乎不是一个荒谬的想法。

Android操作系统会始终随机终止并重新启动用户应用/服务。以我的经验,它无疑帮助我更深入地思考错误条件以及设计更可靠的体系结构。


4
Android的动作不是随机的,但活动需要在被告知时能够保存状态。有细微但重要的区别。
Blrfl 2013年

从我读过什么也没有保证onDestroyonPauseonSaveInstanceState,等......将永远不会在一个活动或服务调用。在应用程序级别上甚至没有onDestory回调。所以是的,有一些挂钩可以正常关闭,但是您仍然必须为随机退出做好准备。
哈维2013年

您可以确保onPause()在活动被杀死之前可以拨打电话。在Honeycomb之后,您可以肯定加号onStop()。Android应用仅仅是碰巧相关的活动的集合,就执行生命周期而言,没有任何应用级别的概念。
Blrfl 2013年

很高兴知道。
哈维2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.