如何避免Akka Actor在抛出异常时被重新加载?
解决Actor抛出异常后阻止重启的问题
哦,我懂你遇到的坑了——你对Akka中supervisorStrategy的作用范围理解错啦!你在MyActor里重写的这个策略,是用来定义这个Actor如何监管它自己的子Actor的规则,而不是用来决定它自己出故障时会被怎么处理的。你的MyActor是被ActorSystem的根守护Actor监管的,而根守护的默认策略就是重启故障Actor,所以你的代码完全没起到你想要的效果。
正确的实现方式
要让MyActor抛异常后直接停止不重启,你得让它的父Actor用Stop的监管策略。最靠谱的做法是自己写一个监管Actor,让它来管理MyActor,并在这个监管Actor里设置正确的策略:
import akka.actor.{Actor, ActorSystem, OneForOneStrategy, Props, SupervisorStrategy} class MyActor extends Actor { println("Created new actor") def receive = { case msg => println("Received message: " + msg) throw new Exception() } } class SupervisingActor extends Actor { // 定义监管规则:不管子Actor抛什么Exception,直接停止它 override val supervisorStrategy = OneForOneStrategy() { case _: Exception => SupervisorStrategy.Stop } // 在监管Actor的上下文里创建MyActor,这样它就是子Actor了 val child = context.actorOf(Props[MyActor], "myChild") def receive = { // 把收到的消息转发给子Actor case msg => child forward msg } } object Test extends App { val system = ActorSystem("Test") val supervisor = system.actorOf(Props[SupervisingActor], "supervisor") supervisor ! "Hello" }
跑这段代码你就会发现,Created new actor只会打印一次,异常抛出后MyActor直接被停止,不会再重启。
为啥原来的代码没用?
当你直接调用system.actorOf(Props(new MyActor()))时,MyActor的父Actor是Akka系统的根守护Actor,它的默认策略是:遇到Exception类型的故障时执行Restart操作,所以你的MyActor才会被重启,导致那句创建日志打了两次。
记住:只有Actor的父Actor才能决定它出故障后的处理策略——这就是为什么我们需要自定义监管Actor的核心原因。
内容的提问来源于stack exchange,提问作者user79074
相关产品推荐
相关产品推荐

