3

如果我在 Scala 中为演员定义主管策略,我如何同时使用OneForOneStrategyAllForOneStrategy?有没有一种简单的方法来组合它们,还是我必须定义一个自定义SupervisorStrategy?这是一个例子:

class MyActor extends Actor {
  override val supervisorStrategy = OneForOneStrategy() {
    case _: NullPointerException  => Restart
    case _: FileNotFoundException => Restart // here I want to restart all children
    case _: Exception             => Escalate
  }
}

如果我必须编写自己的主管策略,我该怎么做?我没有找到任何例子。

4

1 回答 1

0

您必须定义自定义主管策略。对于您的特定用例,以下自定义策略将起作用:

package akka.actor

import java.io.FileNotFoundException
import scala.concurrent.duration._

case class CustomStrategy(
  maxNrOfRetries:              Int      = -1,
  withinTimeRange:             Duration = Duration.Inf,
  override val loggingEnabled: Boolean  = true)(val decider: SupervisorStrategy.Decider)
  extends SupervisorStrategy {

  import SupervisorStrategy._

  private val retriesWindow = (maxNrOfRetriesOption(maxNrOfRetries), withinTimeRangeOption(withinTimeRange).map(_.toMillis.toInt))

  def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRef]): Unit = ()

  def processFailure(context: ActorContext, restart: Boolean, child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]): Unit = {
    if (cause.isInstanceOf[FileNotFoundException]) {
      // behave like AllForOneStrategy
      if (children.nonEmpty) {
        if (restart && children.forall(_.requestRestartPermission(retriesWindow)))
          children foreach (crs ⇒ restartChild(crs.child, cause, suspendFirst = (crs.child != child)))
        else
          for (c ← children) context.stop(c.child)
      }
    } else {
      // behave like OneForOneStrategy
      if (restart && stats.requestRestartPermission(retriesWindow))
        restartChild(child, cause, suspendFirst = false)
      else
        context.stop(child)
    }
  }
}

是测试上述策略的要点。该规范创建了一个使用CustomStrategy并创建两个孩子的主管。当一个孩子抛出 aNullPointerException时,只有那个孩子被重新启动;当一个孩子抛出 a 时FileNotFoundException,两个孩子都会重新启动。

关于自定义策略的几点说明:

  • 它扩展SupervisorStrategy并模仿此处定义的现有策略。
  • 它在akka.actor包内定义,可以访问那里的包私有成员。
  • processFailure,必须在扩展类中重写的方法之一SupervisorStrategy,被调用Restart并且Stop,因此对于您的场景,我们在那里定义自定义行为。
于 2017-07-07T02:16:47.707 回答