简体   繁体   English

Akka Java容错和actor重启

[英]Akka Java fault tolerance and actor restarting

I'm currently looking into Fault Tolerance and Supervisor strategies in Akka (Java version). 我目前正在研究Akka(Java版)中的Fault Tolerance和Supervisor策略。

at ... http://doc.akka.io/docs/akka/2.3.2/java/fault-tolerance.html and http://doc.akka.io/docs/akka/2.3.2/general/supervision.html#supervision 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#监督

A few questions: 几个问题:

1) Should we ever use try/catch blocks in our actors when we know what kind of exceptions to expect? 1)当我们知道期望什么样的例外时,我们是否应该在演员中使用try / catch块? Why or why not? 为什么或者为什么不? If not, should we depend on a supervisor strategy to effectively handle exceptions that a child might throw? 如果没有,我们是否应该依靠主管策略来有效处理孩子可能抛出的异常?

2) By default, if no supervisor is configured explicitly in a parent actor, it looks like any child actor who throws an exception will be restarted by default. 2)默认情况下,如果在父actor中没有显式配置管理程序,则默认情况下将重启任何抛出异常的子actor。 What if none of your actors in your entire system carry state...Should we really be doing restarts? 如果整个系统中的所有演员都没有状态怎么办...我们真的应该重启吗?

3) What if your top-level actors created by system.actorOf( ... ) throws an exception? 3)如果由system.actorOf(...)创建的顶级actor会引发异常怎么办? How do you provide a supervisor strategy outside of the actor system? 你如何在演员系统之外提供监督策略?

4) Let's assume a scenario in which actor A has a child actor B. Now let's say Actor A asks Actor B to do some work. 4)让我们假设一个场景,其中演员A有一个儿童演员B.现在让我们说演员A要求演员B做一些工作。

Some code might look like this: 有些代码可能如下所示:

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    
    }

Now... what if actor A somehow throws an exception. 现在......如果演员A以某种方式抛出异常会怎样。 By default it is restarted by its supervisor. 默认情况下,它由主管重新启动。 The question is, does the onComplete "closure" still get executed sometime in the future, or is it effectively "wiped out" on the restart? 问题是,onComplete“闭包”是否仍会在将来的某个时间执行,还是在重启时有效“消失”?

5) Let's assume I have a hierarchy as such as: A->B->C. 5)假设我有一个层次结构,如:A-> B-> C. Let's also assume that I override preRestart so that I effectively do NOT stop my children. 我们也假设我覆盖preRestart,这样我就不会阻止我的孩子。 On A's prestart he calls getContext().actorOf(B), and in B's prestart he calls getContext().actorOf(C). 在A的预启动时,他调用getContext()。actorOf(B),并在B的预启动中调用getContext()。actorOf(C)。 If A throws an exception, will more than one actor B and more than one actor C now exist in the system? 如果A抛出异常,系统中是否会存在多个actor B和多个actor C?

Thanks! 谢谢!

This is going to be a pretty long answer, but let me tackle your points as orderly as possible. 这将是一个很长的答案,但让我尽可能有序地解决你的观点。
Also, I will rely on the official Akka documentation, as I believe Akka to be one of the best documented projects out there and I don't want to reinvent the wheel. 此外,我将依赖官方Akka文档,因为我相信Akka是最好的文档项目之一,我不想重新发明轮子。 :) :)

  1. A good introduction/overview of the way fault tolerance works in Akka is [1] . 对Akka中容错工作方式的一个很好的介绍/概述是[1] I think that article “sums up” quite well several pages of the Akka docs. 我认为这篇文章很好地总结了几页Akka文档。 To respond specifically to this point, I think it depends: you can try/catch exceptions, sure, but the Error Kernel Pattern states that you should “ push down the actor hierarchy ” anything that can fail (this is to prevent or limit as much as possible the loss of state within actors). 为了特别回应这一点,我认为这取决于:你可以try/catch异常,当然,但是错误内核模式声明你应该“ 压低actor层次结构 ”任何可能失败的东西(这是为了防止或限制尽可能多的尽可能在演员中失去国家)。 This said, if you have a very specific Exception and you know how to handle it as part of the processing of a message, I don't think there is any intrinsic problem in catching it. 这就是说,如果你有一个非常具体的Exception并且你知道如何处理它作为处理消息的一部分,我认为捕获它没有任何内在问题。 In fact, I can think of at least one specific case where you want to catch exceptions and handle them: if your actor is responding to a Pattern.ask , you need to wrap exceptions in Failure if you want the caller to be notified. 实际上,我至少可以想到一个特殊情况,你捕获异常并处理它们:如果你的actor正在响应Pattern.ask ,你需要在Failure包含异常,如果你想要通知调用者。 ( [2] ). [2] )。

  2. As stated in [3] , the default behaviour is indeed Restart , but only in case an Exception is thrown during the message processing. [3]中所述,默认行为确实是Restart ,但仅在消息处理期间抛出Exception情况下。 Notice that ActorInitializationException and ActorKilledException will, by default, terminate the child instead and keep in mind that any Exception thrown within preStart will be wrapped in a ActorInitializationException . 请注意,默认情况下, ActorInitializationExceptionActorKilledException终止ActorKilledException ,并记住在preStart抛出的任何Exception都将包装在ActorInitializationException As to the whether Restart is a sound default “in case you don't have state in your actors”...well, an Actor is, by definition, an abstraction to safely access and manipulate state in a concurrent environment: if you don't have state, you might as well use Future s instead of actors, probably. 至于Restart是否是声音默认“万一你的演员没有状态”......好吧,根据定义,一个演员是一个在并发环境中安全访问和操纵状态的抽象:如果你不喜欢没有状态,你可能也可以使用Future而不是演员。 In general, Restart was deemed a safe and reasonable default for a typical use case. 通常,对于典型用例, Restart被视为安全且合理的默认设置。 In your specific case (which is not a typical use-case for an actor system), you can override the default supervision strategy anyways. 在您的特定情况下(这不是演员系统的典型用例),您无论如何都可以覆盖默认监督策略。

  3. Top-level actors are top level only from the “ user ” point of view. 顶级角色仅从“ 用户 ”的角度来看是顶级的。 As explained in [4] , any top-level actor is created as a child of the Guardian actor, and it has a normal default supervision strategy. [4]中所述 ,任何顶级actor都是作为Guardian actor的子级创建的,它具有正常的默认监督策略。 Also, you can modify such default using the property akka.actor.guardian-supervisor-strategy . 此外,您可以使用属性akka.actor.guardian-supervisor-strategy修改此类默认值。 Also, keep in mind that you should always design you systems keeping Akka's hierarchical nature ( [5] ) in mind, hence not using top-level actors too much ( [6] ). 另外,请记住,你应该始终设计你的系统,记住Akka的层次性( [5] ),因此不要过多地使用顶级演员( [6] )。

  4. Whether onComplete 's callbacks will be called or not depends on when A fails. 是否调用onComplete的回调取决于A何时失败。 If it fails after B completed and responded to A's request, then it might execute. 如果 B完成并且响应A的请求失败,那么它可能会执行。 Otherwise it will not. 否则它不会。 It is “wiped out” when with the old A instance. 使用旧的A实例时,它会“消失”。

  5. This is a bit confusing, but I will assume the following: 这有点令人困惑,但我会假设如下:

    • When you say “ A throws an Exception”, you mean within message processing ( onReceive ) 当你说“ A抛出异常”时,你的意思是在消息处理中( onReceive
    • You have a field in your actor that will store the ref returned by getContext().actorOf(C) . 你的actor中有一个字段,用于存储getContext().actorOf(C)返回的ref。

The quick answer is: yes . 快速回答是: 是的 Given the scenario you describe, there will be multiple instances of B and C . 根据您描述的场景,将有多个BC实例。 The new instance of A will not know that however. 然而, A的新实例不会知道。 It will have a reference to the new B and, indirectly, the new C . 它将引用新的B并间接引用新的C This is reasonable and expected, because you have manually and explicitly disabled a default piece of cleanup logic that handles failures in an actor hierarchy (by changing postRestart ): it is now your responsibility to cleanup and the preStart implementation you describe does not do it. 这是合理的,也是预期的,因为您手动明确地禁用了一个处理actor层次结构中的失败的默认清理逻辑(通过更改postRestart ):现在您有责任进行清理,并且您描述的preStart实现不会这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM