10

我目前正在研究 Akka(Java 版本)中的容错和主管策略。

在 ... http://doc.akka.io/docs/akka/2.3.2/java/fault-tolerance.htmlhttp://doc.akka.io/docs/akka/2.3.2/general/监督.html#supervision

几个问题:

1) 当我们知道会出现什么样的异常时,我们是否应该在我们的演员中使用 try/catch 块?为什么或者为什么不?如果不是,我们是否应该依靠主管策略来有效处理孩子可能抛出的异常?

2)默认情况下,如果没有在父actor中显式配置supervisor,看起来任何抛出异常的子actor都会默认重启。如果你的整个系统中没有一个actors携带状态……我们真的应该重新启动吗?

3) 如果由 system.actorOf( ... ) 创建的顶级演员抛出异常怎么办?你如何在演员系统之外提供监督者策略?

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 “关闭”是否仍会在未来某个时间执行,还是在重新启动时有效地“清除”?

5)假设我有一个层次结构,例如:A->B->C。让我们还假设我覆盖了 preRestart ,这样我就不会有效地阻止我的孩子。在 A 的预启动时,他调用 getContext().actorOf(B),在 B 的预启动时,他调用 getContext().actorOf(C)。如果 A 抛出异常,系统中是否会存在多个参与者 B 和多个参与者 C?

谢谢!

4

1 回答 1

9

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

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

  2. [3]中所述,默认行为确实是Restart,但仅在Exception消息处理期间抛出 an 的情况下。请注意,默认情况下,ActorInitializationExceptionand会终止子进程,并记住任何抛出的内容都将被包裹在. 至于“如果你的actors中没有状态”是否是一个声音默认值......好吧,根据定义,一个actor是在并发环境中安全访问和操作状态的抽象:如果你没有'没有状态,您可能还不如使用s 而不是演员。一般来说,ActorKilledExceptionExceptionpreStartActorInitializationExceptionRestartFutureRestart 被认为是典型用例的安全且合理的默认值。在您的特定情况下(这不是演员系统的典型用例),您无论如何都可以覆盖默认的监督策略。

  3. 顶级参与者仅从“<em>用户”的角度来看是顶级的。正如[4]中所解释的,任何顶级 Actor 都是作为Guardian Actor 的子级创建的,并且它具有正常的默认监督策略。此外,您可以使用属性修改此类默认值akka.actor.guardian-supervisor-strategy。另外,请记住,在设计系统时应始终牢记 Akka 的分层特性([5]),因此不要过多地使用顶级参与者([6])。

  4. 是否onComplete会调用 的回调取决于 A 何时失败。如果在B 完成并响应 A 的请求后它失败了,那么它可能会执行。否则不会。当使用旧的 A 实例时,它会被“清除”。

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

    • 当你说“<code>A throws an Exception”时,你的意思是在消息处理中(onReceive
    • 您的演员中有一个字段将存储由getContext().actorOf(C).

快速的回答是:的。B鉴于您描述的场景,将有和的多个实例C。然而,新的实例A不会知道这一点。它将引用新的B,间接地,新的C。这是合理且符合预期的,因为您已经手动显式禁用了处理参与者层次结构中的故障的默认清理逻辑(通过更改postRestart):现在清理是您的责任,而preStart您描述的实现不会这样做。

于 2015-04-08T14:48:31.580 回答