我目前正在研究Akka(Java版)中的Fault Tolerance和Supervisor策略。
at ... http://doc.akka.io/docs/akka/2.3.2/java/fault-tolerance.html和http://doc.akka.io/docs/akka/2.3.2/general/supervision.html#supervision
几个问题:
1)当我们知道期望什么样的例外时,我们是否应该在演员中使用try / catch块?为什么或者为什么不?如果没有,我们是否应该依靠主管策略来有效处理孩子可能抛出的异常?
2)默认情况下,如果在父actor中没有显式配置管理程序,则默认情况下将重启任何抛出异常的子actor。如果整个系统中的任何一个演员都没有状态怎么办...我们真的应该重新开始吗?
3)如果system.actorOf(...)创建的顶级actor会引发异常怎么办?你如何在演员系统之外提供监督策略?
4)让我们假设演员A有一个儿童演员B.现在让我们说演员A要求演员B做一些工作。
有些代码可能如下所示:
Future<Object> future = Patterns.ask(child, message, timeout);
future.onComplete(new OnComplete<Object>() {
@Override
public void onComplete(Throwable failure, Object result) throws Throwable {
... handle here
}
现在......如果演员A以某种方式抛出异常会怎样。默认情况下,它由主管重新启动。问题是,onComplete&#34;关闭&#34;仍然会在将来的某个时候被执行,或者它是否有效地被消灭了#34;在重启?
5)假设我有一个等级,如:A-> B-> C。我们也假设我覆盖preRestart,这样我就不会阻止我的孩子。在A的预启动中,他调用getContext()。actorOf(B),并在B&#39的预启动中调用getContext()。actorOf(C)。如果A抛出异常,系统中是否会存在多个actor B和多个actor C?
谢谢!
答案 0 :(得分:8)
这将是一个很长的答案,但让我尽可能有序地解决你的观点 此外,我将依赖官方Akka文档,因为我相信Akka是最好的文档项目之一,我不想重新发明轮子。 :)
在Akka中,容错工作方式的一个很好的介绍/概述是 [1]。我认为这篇文章很好地总结了几页Akka文档。为了特别回应这一点,我认为这取决于:你可以try/catch
例外,当然,错误内核模式表明你应该“推下行为者层次结构“任何可能失败的东西(这是为了尽可能地防止或限制演员内部的状态损失)。这就是说,如果你有一个非常具体的Exception
并且你知道如何处理它作为处理消息的一部分,我认为捕获它没有任何内在问题。事实上,我至少可以想到一个特定的情况,你想要来捕获异常并处理它们:如果你的actor正在响应Pattern.ask
,你需要在{{中包装异常1}}如果您希望通知来电者。 ([2])。
如 [3]中所述,默认行为确实是Failure
,但仅限于在邮件处理期间抛出Restart
的情况。请注意,默认情况下,Exception
和ActorInitializationException
将终止,并请记住,ActorKilledException
中引发的任何Exception
都将被包裹在preStart
中。
至于ActorInitializationException
是否是一个合理的默认值“以防你的演员中没有状态”......好吧,根据定义,一个Actor是在并发环境中安全访问和操纵状态的抽象:如果你没有状态,你可能也可以使用Restart
而不是演员。一般而言,Future
被视为典型用例的安全且合理的默认值。在您的特定情况下(这不是演员系统的典型用例),您仍可以覆盖默认监督策略。
顶级演员仅从“用户”的角度来看是顶级的。如 [4]中所述,任何顶级actor都是作为 Guardian actor的子级创建的,并且它具有正常的默认监督策略。此外,您可以使用属性Restart
修改此类默认值。
另外,请记住,您应始终设计系统,以保持Akka的层次性([5]),因此不要过多地使用顶级演员([6])。
是否会调用akka.actor.guardian-supervisor-strategy
的回调取决于A何时失败。如果在>> B完成并且响应A的请求后失败,那么它可能会执行。否则它不会。使用旧的A实例时,它会“消失”。
这有点令人困惑,但我会假设以下内容:
onComplete
抛出异常”时,您的意思是在邮件处理中(A
)onReceive
返回的引用。 快速回答是:是。根据您描述的方案,将有多个getContext().actorOf(C)
和B
的实例。然而,C
的新实例不会知道这一点。它将引用新的A
,并间接引用新的B
。这是合理的,也是预期的,因为您已经手动并且显式禁用了一个处理actor层次结构中的失败的默认清理逻辑(通过更改C
):现在您有责任进行清理,并且您描述的postRestart
实施不会这样做。