Scala Akka:如何将一对一战略和全对一战略结合起来

Scala Akka:如何将一对一战略和全对一战略结合起来,scala,akka-supervision,Scala,Akka Supervision,如果我在Scala中为参与者定义了主管策略,那么如何同时使用OneForOneStrategy和AllForOneStrategy?是否有一种简单的方法将它们结合起来,或者我必须定义一个自定义的监管策略? 以下是一个例子: class MyActor extends Actor { override val supervisorStrategy = OneForOneStrategy() { case _: NullPointerException => Restart

如果我在Scala中为参与者定义了主管策略,那么如何同时使用
OneForOneStrategy
AllForOneStrategy
?是否有一种简单的方法将它们结合起来,或者我必须定义一个自定义的
监管策略
? 以下是一个例子:

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

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

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

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
的主管,并创建了两个子项。当一个子系统抛出一个
NullPointerException
时,只有该子系统重新启动;当一个子系统抛出
FileNotFoundException
时,两个子系统都会重新启动

关于自定义策略的一些注意事项:

  • 它扩展了现有定义的策略,并按照这些策略建模
  • 它在
    akka.actor
    包中定义,以访问包中的私有成员
  • ,在扩展
    SupervisorStrategy
    的类中必须重写的方法之一被调用,因此对于您的场景,我们在其中定义自定义行为

我很惊讶,它必须在
akk.actor
中定义。为了使其更通用,还可以覆盖OneForOneStartegy,并添加一个
RestartAll
和一个
StopAll
决策器指令,对吗?应该避免覆盖
OneForOneStrategy
,因为它是一个案例类。扩展
Decider
类型也是不可能的,因为它是密封的,并且规范(
Resume
Restart
,…)是case对象(因此我也不能扩展
Restart
来创建
RestartAll
)。为了使示例更加通用,有必要编写一个全新的SupervisorStrategy类。