2017-09-14 133 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" 

    } 
} 

在這種情況下,從童星異常將被上報給根演員。