Akka Java容错和actor重启

HiC*_*123 9 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#监督

几个问题:

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    
    }
Run Code Online (Sandbox Code Playgroud)

现在......如果演员A以某种方式抛出异常会怎样.默认情况下,它由主管重新启动.问题是,onComplete"闭包"是否仍会在将来的某个时间执行,还是在重启时有效"消失"?

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

谢谢!

mdm*_*mdm 8

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

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

  2. [3]中所述,默认行为确实如此Restart,但仅限于Exception在消息处理期间抛出的情况.请注意,ActorInitializationExceptionActorKilledException会在默认情况下,终止子来代替,记住,任何Exception内抛出了preStart将被包裹在一个ActorInitializationException.至于是否Restart是声音默认"万一你的演员没有状态"......好吧,根据定义,一个演员是在并发环境中安全访问和操纵状态的抽象:如果你不'有状态,你可能也可以使用Futures代替演员.通常,Restart 对于典型用例,被视为安全合理的默认值.在您的特定情况下(这不是演员系统的典型用例),您无论如何都可以覆盖默认监督策略.

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

  4. 是否onComplete会调用回调取决于A何时失败.如果 B完成并且响应A的请求失败,那么它可能会执行.否则它不会.使用旧的A实例时,它会"消失".

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

    • 当你说" A抛出异常"时,你的意思是在消息处理中(onReceive)
    • 你的actor中有一个字段,用于存储返回的ref getContext().actorOf(C).

快速回答是:是的.根据您描述的场景,将会有多个B和的实例C.然而,新的实例A不会知道.它将引用新的B,间接的,新的C.这是合理的,也是预期的,因为您已手动显式禁用了一个处理actor层次结构中的失败的默认清理逻辑(通过更改postRestart):现在您有责任清理并且preStart您描述的实现不会执行此操作.