预定义策略

顶层的actor在/user下面并且有/user来监督。 user的默认策略是,收到异常就把actor重启,除非是内部异常表明actor是被杀死的或者初始化失败,此时就会停止actor。 这种策略就是默认策略。 这个策略的顶层监护人是可以改变的,我们会在第四节看到。 每个演员都有默认的监管策略,可以通过supervisorStrategy方法修改。 SupervisorStrategy对象提供了两个预定义的策略:defaultStrategy和stoppingStrategy。 正如名字所暗示的,默认策略就是所有actor默认的策略,只要你不改变,所有actor都使用默认策略。 默认策略在SupervisorStrategy中被定义为下面的形式:

Listing 4.10 Default Supervisor Strategy

    final val defaultStrategy: SupervisorStrategy = {
    def defaultDecider: Decider = { //
    // 1
    case _: ActorInitializationException => Stop //
    // 2
    case _: ActorKilledException => Stop
    case _: Exception => Restart
    }
    OneForOneStrategy()(defaultDecider) //
    // 3
    }


1.  Decider通过模式匹配选择一个异常指令。
2.  Stop, Start, Resume和Escalate被称为指令。
3.  OneForOneStrategy返回defaultStrategy的调用。

上面的代码使用了OneForOneStrategy,这个方法我们还没有讨论过。 Akka提供了两种方法来决定actor的命运:所有的孩子有相同的命运或者相同的命运应有在某些孩子上。 某些情况我们可能想停止失败的actor。 某些情况下我们可能像停止所有的actor,一旦它们中的一个失败,可能它们都依赖相同的资源。 如果抛出一个异常,表明一个所有actor都共享的资源一个不可用了,我们应该立即停止所有actor,而不是等待每个actor都去捕获这个异常。 OneForOneStrategy决定子actor之间不共享命运,只有崩溃的actor会被Decider裁决。 另外一种选择是使用AllForOneStrategy,一旦一个actor崩溃,所有actor都被裁决。 下一节我们将更加详细的描述 OneForOneStrategy和AllForOneStrategy。 下面的代码显示了SupervisorStrategy中stoppingStrategy的定义。

Listing 4.11 Stopping Supervisor Strategy

    final val stoppingStrategy: SupervisorStrategy = {
    def stoppingDecider: Decider = {
    case _: Exception => Stop //
    // 1
    }
    OneForOneStrategy()(stoppingDecider)
    }

1.  收到任何异常都停止。

停止策略会停止任何异常的actor。 这些内建的策略没有什么特别之处。 你可以用相同的方式来定义你的自定义策略。 如果一个actor用了stoppingStrategy策略,一旦ThreadDeath或者OutOfMemoryError异常被抛出,将会发生什么? 任何supervisor没有捕获的可抛出对象,都会被抛给更上层的supervisor。 如果致命错误被一路攀升到user,user使用的是默认策略,也不会处理它。 这种情况下,未捕获的异常会引起整个actor系统的崩溃。 这就是我们要在第四章后面要看到的,我们可以配置这种情况发生时的策略是退出JVM还是关闭actor系统。 大多数情况下,不处理致命错误而是关闭actor系统是个好策略,因为系统无法从致命错误中恢复。