TheAkkaWay
TheAkkaWay copied to clipboard
Kill 不起作用?
Akka的文档里有 You can kill an actor by sending a Kill message. This will cause the actor to throw a ActorKilledException, triggering a failure. The actor will suspend operation and its supervisor will be asked how to handle the failure, which may mean resuming the actor, restarting it or terminating it completely.
// kill the 'victim' actor
victim ! Kill
我想让一个actor给自己发一个Kill消息,然后让parent来restart他
import akka.actor._
case class Msg(n: Int)
object MyActor {
def props: Props = Props[MyActor]
}
class MyActor extends Actor {
override def preStart() = {
println("actor start")
self ! Msg(1)
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
println("preRestart")
super.preRestart (reason, message)
}
def receive = {
case Msg(i) =>
if(i == 10)
self ! Kill
// throw new Exception("kill exception")
else {
println(s"receive ${i}")
self ! Msg(i + 1)
}
}
}
object Parent {
def props: Props = Props[Parent]
}
class Parent extends Actor {
import akka.actor.OneForOneStrategy
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
OneForOneStrategy(maxNrOfRetries = 60, withinTimeRange = 1 minute) {
case _: ActorKilledException =>
println("killed")
Restart
case _: Exception =>
println("other")
Restart
}
def receive = {
case t => println("this is e,,,," + t)
}
val c = context.actorOf(MyActor.props, "c")
}
object Main extends App {
val system: ActorSystem = ActorSystem("helloAkka")
val a = system.actorOf(Parent.props, "a")
}
得到的结果是
actor start
receive 1
receive 2
receive 3
receive 4
receive 5
receive 6
receive 7
receive 8
receive 9
[ERROR] [05/25/2017 17:08:25.209] [helloAkka-akka.actor.default-dispatcher-6] [akka://helloAkka/user/a/c] Kill (akka.actor.ActorKilledException: Kill)
并没有restart, 如果不用Kill, 而是直接抛出异常确实可以restart的,这是什么原因呢?
Kill会实际上抛出的是ActorKilledException, 而这个异常在supervisor strategy的Decider是Stop,而不是Restart。
final val defaultDecider: Decider = {
case _: ActorInitializationException ⇒ Stop
case _: ActorKilledException ⇒ Stop
case _: DeathPactException ⇒ Stop
case _: Exception ⇒ Restart
}
如果要模拟Restart,可以在parent中将ActorKilledException的Decider改为Restart
@PipsqueakH 楼上是正解。不过你的需求还挺特殊的,使用actor一般会主动stop,很少见主动restart的。