[英]Akka Java fault tolerance and actor restarting
我目前正在研究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#监督
几个问题:
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“闭包”是否仍会在将来的某个时间执行,还是在重启时有效“消失”?
5)假设我有一个层次结构,如:A-> B-> C. 我们也假设我覆盖preRestart,这样我就不会阻止我的孩子。 在A的预启动时,他调用getContext()。actorOf(B),并在B的预启动中调用getContext()。actorOf(C)。 如果A抛出异常,系统中是否会存在多个actor B和多个actor C?
谢谢!
这将是一个很长的答案,但让我尽可能有序地解决你的观点。
此外,我将依赖官方Akka文档,因为我相信Akka是最好的文档项目之一,我不想重新发明轮子。 :)
对Akka中容错工作方式的一个很好的介绍/概述是[1] 。 我认为这篇文章很好地总结了几页Akka文档。 为了特别回应这一点,我认为这取决于:你可以try/catch
异常,当然,但是错误内核模式声明你应该“ 压低actor层次结构 ”任何可能失败的东西(这是为了防止或限制尽可能多的尽可能在演员中失去国家)。 这就是说,如果你有一个非常具体的Exception
并且你知道如何处理它作为处理消息的一部分,我认为捕获它没有任何内在问题。 实际上,我至少可以想到一个特殊情况,你想捕获异常并处理它们:如果你的actor正在响应Pattern.ask
,你需要在Failure
包含异常,如果你想要通知调用者。 ( [2] )。
如[3]中所述,默认行为确实是Restart
,但仅在消息处理期间抛出Exception
情况下。 请注意,默认情况下, ActorInitializationException
和ActorKilledException
将终止子ActorKilledException
,并记住在preStart
抛出的任何Exception
都将包装在ActorInitializationException
。 至于Restart
是否是声音默认“万一你的演员没有状态”......好吧,根据定义,一个演员是一个在并发环境中安全访问和操纵状态的抽象:如果你不喜欢没有状态,你可能也可以使用Future
而不是演员。 通常,对于典型用例, Restart
被视为安全且合理的默认设置。 在您的特定情况下(这不是演员系统的典型用例),您无论如何都可以覆盖默认监督策略。
顶级角色仅从“ 用户 ”的角度来看是顶级的。 如[4]中所述 ,任何顶级actor都是作为Guardian actor的子级创建的,它具有正常的默认监督策略。 此外,您可以使用属性akka.actor.guardian-supervisor-strategy
修改此类默认值。 另外,请记住,你应该始终设计你的系统,记住Akka的层次性( [5] ),因此不要过多地使用顶级演员( [6] )。
是否调用onComplete
的回调取决于A何时失败。 如果在 B完成并且响应A的请求后失败,那么它可能会执行。 否则它不会。 使用旧的A实例时,它会“消失”。
这有点令人困惑,但我会假设如下:
A
抛出异常”时,你的意思是在消息处理中( onReceive
) getContext().actorOf(C)
返回的ref。 快速回答是: 是的 。 根据您描述的场景,将有多个B
和C
实例。 然而, A
的新实例不会知道。 它将引用新的B
并间接引用新的C
这是合理的,也是预期的,因为您手动并明确地禁用了一个处理actor层次结构中的失败的默认清理逻辑(通过更改postRestart
):现在您有责任进行清理,并且您描述的preStart
实现不会这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.