Akka:如何结合 OneForOneStrategy 和 AllForOneStrategy
Akka: How to combine OneForOneStrategy and AllForOneStrategy
如果我在 Scala 中为 actor 定义监督者策略,我如何同时使用 OneForOneStrategy
和 AllForOneStrategy
?有没有一种简单的方法来组合它们,还是我必须定义一个自定义 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
}
}
如果我必须编写自己的主管策略,我该怎么做?我找不到这方面的例子。
您必须定义自定义主管策略。对于您的特定用例,可以使用以下自定义策略:
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)
}
}
}
Here是测试上述策略的gist。该规范创建了一个使用 CustomStrategy
的主管,并创建了两个 children。当一个 child 抛出一个 NullPointerException
时,只有那个 child 被重新启动;当 child 抛出 FileNotFoundException
时,两个 children 都会重新启动。
关于自定义策略的几点说明:
- 它扩展了
SupervisorStrategy
and is modeled after the existing strategies defined here。
- 它在
akka.actor
包内定义,可以访问那里的 package-private 成员。
processFailure
, one of the methods that must be overridden in classes that extend SupervisorStrategy
, is called on Restart
and Stop
,因此对于您的场景,我们在那里定义了自定义行为。
如果我在 Scala 中为 actor 定义监督者策略,我如何同时使用 OneForOneStrategy
和 AllForOneStrategy
?有没有一种简单的方法来组合它们,还是我必须定义一个自定义 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
}
}
如果我必须编写自己的主管策略,我该怎么做?我找不到这方面的例子。
您必须定义自定义主管策略。对于您的特定用例,可以使用以下自定义策略:
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)
}
}
}
Here是测试上述策略的gist。该规范创建了一个使用 CustomStrategy
的主管,并创建了两个 children。当一个 child 抛出一个 NullPointerException
时,只有那个 child 被重新启动;当 child 抛出 FileNotFoundException
时,两个 children 都会重新启动。
关于自定义策略的几点说明:
- 它扩展了
SupervisorStrategy
and is modeled after the existing strategies defined here。 - 它在
akka.actor
包内定义,可以访问那里的 package-private 成员。 processFailure
, one of the methods that must be overridden in classes that extendSupervisorStrategy
, is called onRestart
andStop
,因此对于您的场景,我们在那里定义了自定义行为。