2017-09-14 57 views
1

传播例外,我有一个简单的演员的层次结构,看起来如下:在阿卡

root 
    | 
    -- parent1 
    | | 
    | -- child1_1 
    | | 
    | -- child1_2 
    | 
    -- parent2 
     | 
     -- child2_1 
     | 
     -- child2_2 

root实现supervisorStrategy处理各种异常。
如果在parent1parent2中发生未处理的异常,则达到supervisorStrategy,并且适当地执行处理。
如果任何孩子发生未处理的异常,那么我只得到[ERROR] akka.actor.OneForOneStrategy,就是这样。

我该如何获得层次结构中的任何未处理的错误向上传播并到达root将在哪里处理?

我需要处理监督并将Escalate添加到每个级别?

回答

1

默认监管策略是重新启动如果异常类型为Exception(或其子),则为子actor。

当主管战略不是一个演员以下例外是默认处理定义:

ActorInitializationException将停止失败童星

ActorKilledException将停止失败童星

DeathPactException将停止失败的子演员

例外将 重新启动t他失败童星

其他类型的Throwable将被升级到父演员

所以,是的,你需要监管策略添加到在这种情况下每个级别。

例子:

import akka.actor.SupervisorStrategy.{Escalate, Restart, Resume, Stop} 
import akka.actor.{Actor, ActorLogging, ActorSystem, OneForOneStrategy, Props} 

import scala.concurrent.duration._ 

class RootActor extends Actor with ActorLogging { 

    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { 
     case _: Exception    => { 
     log.info("Got exception in root") 
     Escalate 
     } 
    } 

    override def receive: Receive = { 
    case "START_ROOT" => 
     log.info("Started root actor") 
     val parentActor = context.actorOf(Props(classOf[ParentActor])) 
     parentActor ! "START_PARENT" 
    } 
} 

class ParentActor extends Actor with ActorLogging { 
    override val supervisorStrategy = 
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { 
     case _: Exception    => { 
     log.info("Got exception in parent") 
     Escalate 
     } 
    } 

    override def receive: Receive = { 
    case "START_PARENT" => 
     log.info("Started parent actor") 
     val childActor = context.actorOf(Props(classOf[ChildActor])) 
     childActor ! "START_CHILD" 
    } 
} 

class ChildActor extends Actor with ActorLogging { 
    override def receive: Receive = { 
    case "START_CHILD" => 
     throw new Exception("Exception from CHILD ACTOR") 
     log.info("Started child actor") 
    } 

    override def preRestart(reason: Throwable, message: Option[Any]): Unit = { 
    log.info("Restarting child actor") 
    super.preRestart(reason, message) 
    } 
} 
object App { 
    def main(args: Array[String]): Unit = { 

    val system = ActorSystem("my-system") 
    val rootActor = system.actorOf(Props(classOf[RootActor])) 
    rootActor ! "START_ROOT" 

    } 
} 

在这种情况下,从童星异常将被上报给根演员。