Akka Java容错和actor重启

时间:2014-05-21 02:49:11

标签: java akka akka-supervision

我目前正在研究Akka(Java版)中的Fault Tolerance和Supervisor策略。

at ... http://doc.akka.io/docs/akka/2.3.2/java/fault-tolerance.htmlhttp://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?

谢谢!

1 个答案:

答案 0 :(得分:8)

这将是一个很长的答案,但让我尽可能有序地解决你的观点 此外,我将依赖官方Akka文档,因为我相信Akka是最好的文档项目之一,我不想重新发明轮子。 :)

  1. 在Akka中,容错工作方式的一个很好的介绍/概述是 [1]。我认为这篇文章很好地总结了几页Akka文档。为了特别回应这一点,我认为这取决于:你可以try/catch例外,当然,错误内核模式表明你应该“推下行为者层次结构“任何可能失败的东西(这是为了尽可能地防止或限制演员内部的状态损失)。这就是说,如果你有一个非常具体的Exception并且你知道如何处理它作为处理消息的一部分,我认为捕获它没有任何内在问题。事实上,我至少可以想到一个特定的情况,你想要来捕获异常并处理它们:如果你的actor正在响应Pattern.ask,你需要在{{中包装异常1}}如果您希望通知来电者。 ([2])。

  2. [3]中所述,默认行为确实是Failure,但仅限于在邮件处理期间抛出Restart的情况。请注意,默认情况下,ExceptionActorInitializationException终止,并请记住,ActorKilledException中引发的任何Exception都将被包裹在preStart中。 至于ActorInitializationException是否是一个合理的默认值“以防你的演员中没有状态”......好吧,根据定义,一个Actor是在并发环境中安全访问和操纵状态的抽象:如果你没有状态,你可能也可以使用Restart而不是演员。一般而言,Future被视为典型用例的安全且合理的默认值。在您的特定情况下(这不是演员系统的典型用例),您仍可以覆盖默认监督策略。

  3. 顶级演员仅从“用户”的角度来看是顶级的。如 [4]中所述,任何顶级actor都是作为 Guardian actor的子级创建的,并且它具有正常的默认监督策略。此外,您可以使用属性Restart修改此类默认值。 另外,请记住,您应始终设计系统,以保持Akka的层次性([5]),因此不要过多地使用顶级演员([6])。

  4. 是否会调用akka.actor.guardian-supervisor-strategy的回调取决于A何时失败。如果在> B完成并且响应A的请求后失败,那么它可能会执行。否则它不会。使用旧的A实例时,它会“消失”。

  5. 这有点令人困惑,但我会假设以下内容:

    • 当您说“onComplete抛出异常”时,您的意思是在邮件处理中(A
    • 您的actor中有一个字段,用于存储onReceive返回的引用。
  6. 快速回答是:。根据您描述的方案,将有多个getContext().actorOf(C)B的实例。然而,C的新实例不会知道这一点。它将引用新的A,并间接引用新的B。这是合理的,也是预期的,因为您已经手动并且显式禁用了一个处理actor层次结构中的失败的默认清理逻辑(通过更改C):现在您有责任进行清理,并且您描述的postRestart实施不会这样做。