想象一个直接的监督层级。孩子死了。父亲决定Restart
孩子。当Restart
编辑时,postRestart
和朋友被召唤,但如果父亲决定恢复孩子怎么办?儿童演员是否知道他正在恢复?顺便说一下。父亲是否可以访问导致他孩子出现异常的消息?
答案 0 :(得分:6)
简历意味着“没有真正发生,继续”,并且本着这种精神,孩子甚至都不知情。这是一个很少使用的指令。
父母只会自己获得失败(即Throwable
),而不是导致问题的信息,因为这会让你把父母和孩子的逻辑纠缠在健康之外。
答案 1 :(得分:1)
术语“恢复”表示继续处理消息,并在文档中的两个位置引用。
第一个用于响应异常状态: 根据akka文档:
As described in Actor Systems supervision describes a dependency relationship between actors: the supervisor delegates tasks to subordinates and therefore must respond to their failures. When a subordinate detects a failure (i.e. throws an exception), it suspends itself and all its subordinates and sends a message to its supervisor, signaling failureDepending on the nature of the work to be supervised and the nature of the failure, the supervisor has a choice of the following four options:
Resume the subordinate, keeping its accumulated internal state
Restart the subordinate, clearing out its accumulated internal state
Terminate the subordinate permanently
Escalate the failure, thereby failing itself
请注意,RESTART实际上是KILLS的原始actor。这里再次使用术语“恢复”来表示继续处理消息。
根据akka文档。
The precise sequence of events during a restart is the following:
- suspend the actor (which means that it will not process normal messages until resumed), and recursively suspend all children
- call the old instance’s preRestart hook (defaults to sending termination requests to all children and calling postStop)
- wait for all children which were requested to terminate (using context.stop()) during preRestart to actually terminate; this—like all actor operations—is non-blocking, the termination notice from the last killed child will effect the progression to the next step
- create new actor instance by invoking the originally provided factory again
- invoke postRestart on the new instance (which by default also calls preStart)
- send restart request to all children which were not killed in step 3; restarted children will follow the same process recursively, from step 2
- resume the actor
答案 2 :(得分:0)
如果您在主管的supervisorStrategy中正确设置了这种行为,则可以将故障冒泡到主管。一个显示该行为的小例子:
import akka.actor.Actor
import akka.actor.Props
import akka.actor.ActorSystem
object SupervisorTest {
def main(args: Array[String]) {
val system = ActorSystem("test")
val master = system.actorOf(Props[Master], "master")
master ! "foo"
Thread.sleep(500)
val worker = system.actorFor("/user/master/foo")
worker ! "bar"
}
}
class Master extends Actor{
import akka.actor.OneForOneStrategy
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
case _: Exception => Escalate
Escalate
}
override def preRestart(ex:Throwable, msg:Option[Any]) = {
println("In master restart: " + msg)
}
def receive = {
case msg:String =>
context.actorOf(Props[Worker], msg)
}
}
class Worker extends Actor{
override def preRestart(ex:Throwable, msg:Option[Any]) = {
println("In worker restart: " + msg)
}
def receive = {
case _ =>
throw new Exception("error!!")
}
}
您可以在Master
演员(我的示例中的主管)中看到,我选择Escalate
Exception
类型的失败。这将导致无法冒泡到preRestart
actor中的Master
。现在我期待msg
param preRestart
成为工人演员的原始违规信息,但事实并非如此。我得到的唯一方法就是覆盖儿童演员的preRestart
。在我的示例中,您将按顺序看到主管和孩子的打印输出。