Akka决策者是否有权访问全部故障场景?
阿卡新来的。创建扩展了Akka决策者是否有权访问全部故障场景?,akka,akka-supervision,Akka,Akka Supervision,阿卡新来的。创建扩展了SupervisorStrategy的新Scala类为我提供了以下模板: class MySupervisorStrategy extends SupervisorStrategy { override def decider: Decider = ??? override def handleChildTerminated(context: ActorContext, child: ActorRef, children: Iterable[ActorRe
SupervisorStrategy
的新Scala类为我提供了以下模板:
class MySupervisorStrategy extends SupervisorStrategy {
override def decider: Decider = ???
override def handleChildTerminated(context: ActorContext, child: ActorRef,
children: Iterable[ActorRef]): Unit = ???
override def processFailure(context: ActorContext, restart: Boolean,
child: ActorRef, cause: Throwable, stats: ChildRestartStats, children: Iterable[ChildRestartStats]): Unit = ???
}
我正在寻找一种访问的方式:
可丢弃的
/异常
ActorRef
决策器(实际上是一个部分函数[Throwable,Directive]
)就会通过Throwable
,但我不知道在哪里可以访问上面列表中的#2和#3有什么想法吗?
更新
从张贴的小提琴来看,它看起来像一个有效的决策者是:
{
case ActorException(ref,t,"stop") =>
println(s"Received 'stop' from ${ref}")
Stop
case ActorException(ref,t,"restart") =>
println(s"Received 'restart' from ${ref}")
Restart
case ActorException(ref,t,"resume") =>
println(s"Received 'resume' from ${ref}")
Resume
}
在上面,我看到了所有三个:
由子级引发的异常
引发异常的子项(ref
)
最初发送给子级的消息(导致引发异常)
看起来在决策者
中没有任何需要在主管
类中定义的内容。我想把Decider
逻辑拉出来,比如说,MyDecider.scala
并找到一种方法来重构Supervisor
,使其supervisorStrategy
使用MyDecider
的实例,因此可能类似于:
class Supervisor extends Actor {
import akka.actor.OneForOneStrategy
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
var child: ActorRef = _
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute, decider = myDecider)
...
}
对于#2,您可以访问发送方“如果策略在监督参与者内部声明”
如果策略是在监督参与者内部声明的(而不是在同伴对象内部),则其决策者可以以线程安全的方式访问参与者的所有内部状态,包括获取对当前失败子级的引用(可用作失败消息的发送者)
该消息不可用,因此唯一的选项是捕获异常,并使用收到的消息抛出自定义异常
这是一个
类ActorSO扩展了Actor{
def_接收:接收={
案例e=>
println(e)
抛出新的RuntimeException(例如toString)
}
最终def接收={
case any=>try{
_接收(任何)
}
抓住{
案例t:Throwable=>抛出新ActorException(self、t、any)
}
}
}
更新
Decider
只是一个PartialFunction
,因此您可以将其传递到构造函数中
对象管理器{
定义道具(决策者:决策者)=道具(新主管(决策者))
}
类监管者(decider:decider)扩展了Actor{
覆盖val supervisorStrategy=OneForOneStrategy()(决策者)
覆盖def接收:接收=???
}
类MyDecider扩展了Decider{
覆盖def isDefinedAt(x:Throwable):布尔值=真
覆盖def应用(v1:可丢弃):监管策略指令={
案例t:ActorException=>Restart
案例不匹配=>SupervisorStrategy.defaultDecider.apply(不匹配)
}
}
对象测试{
val myDecider:Decider={
案例t:ActorException=>Restart
案例不匹配=>SupervisorStrategy.defaultDecider.apply(不匹配)
}
val myDecider2=新的MyDecider()
val系统=ActorSystem(“堆栈溢出”)
val supervisor=system.actorOf(SupervisorActor.props(myDecider))
val-supervisor2=system.actorOf(SupervisorActor.props(myDecider2))
}
这样做,您将无法访问通过sender()
引发异常的子级的ActorRef
这样的监控状态(尽管我们在ActorException
中包含了这一点)
关于您最初从主管处访问导致异常的子消息的问题,您可以看到(从akka 2.5.3)akka开发人员选择不将其用于决策
final protected def handleFailure(f:失败):单元={
//:/currentMessage.message是导致异常的消息!!!
currentMessage=信封(f,f.子项,系统)
getChildByRef(f.child)匹配{
/*
*只有在失败时才采取行动,如果失败来自目前已知的孩子;
*UID可防止接收到来自以下儿童的故障:
*在重新启动前终止,并在重新启动后重新创建
*/
如果stats.uid==f.uid,则使用case Some(stats)⇒
///currentMessage.message未传递给handleFailure!!!
如果(!actor.supervisorStrategy.handleFailure(this,f.child,f.cause,stats,getAllChildStats))抛出f.cause
案例部分(统计)⇒
发布(调试(self.path.toString、clazz(actor),
从旧子级“+f.child+”(uid=“+stats.uid+”!=“+f.uid+”)中删除失败(“+f.cause+”)
无案例⇒
发布(调试(self.path.toString,clazz(actor),“从未知子项“+f.child”删除失败(“+f.cause+”))
}
}
真棒的回答,谢谢@gabrielgiussi(+1)——因此我将监管策略
放入自己的Scala类的动机是使它可以在许多参与者(家长)之间重用。看看你的小提琴,难道我不能在我自己的Scala类中扩展OneForOneStrategy
,并使用你放在其中的相同代码,从而达到我想要的效果吗?然后从每个父级的内部(我想使用这个策略的地方)我可以向类注入一个MyOneForOneStrategy
的实例,然后设置override val-supervisorStrategy=MyOneForOneStrategy
,这行得通吗?再次感谢!应该有一个很好的理由来扩展监管策略,而不是。您应该可以只定义决策者。你想做什么?为什么需要访问消息、子引用和异常?我想构建健壮的容错逻辑。如果决策者可以跨多个参与者重用,并且可以访问所有三个项目,那么我可以定义决策者