我有一个服务,主管负责构建子actor并处理它们的异常。
ServiceMain -> Supervisor -> DiscoveryActor
要构建DiscoveryActor
,请拨打以下内容
Await.result(supervisor ? (Props[Discovery], "Discovery"), Duration.create(60, SECONDS)) match {
case actor: ActorRef =>
discoveryActor = actor
case ex: Exception =>
logger.error("Failed to initialize discovery actor", ex)
sys.exit(1)
}
此代码在Supervisor
def receive = {
case p: Props => sender() ! context.actorOf(p)
case (p: Props, s: String) => sender() ! context.actorOf(p, s)
}
如果DiscoveryActor
无法按照配置研究主机,则preStart()
会在ApiConnectionException
中抛出异常。行为者抛出异常ActorInitializationException
,由akka捕获并变为override val supervisorStrategy =
AllForOneStrategy() {
case _: Exception => Escalate
}
。
我已经厌倦了在Await和superviseStrategy中捕获此异常,如下所示
400 Bad Request Show explanation Loading time: 645
Request headers
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36
Origin: chrome-extension://hgmloofddffdnphfgcellkdfbfbjeloo
Content-Type: multipart/form-data
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Response headers
Date: Thu, 10 Dec 2015 08:30:07 GMT
Server: Apache
X-Request-Id: 8e80edd8-ff10-44f2-9235-6b8d307c179b
X-Runtime: 0.002612
X-Powered-By: Phusion Passenger 4.0.58
Content-Length: 38
Status: 400 Bad Request
Connection: close
Content-Type: application/json; charset=utf-8
但是这些都没有设法抓住它,我试图做的是捕获这样的异常并退出应用程序。
如果有人能够指出我出错的地方或我错过了什么,那么我将非常感激!
答案 0 :(得分:3)
我简化了你的代码只是为了直接找到问题的根源。您可以将其复制并粘贴到编辑器中。它使用 ScalaTest 套件。
SupervisorStrategy
actor 中定义的 Supervisor
确实
Discovery
方法preStart
方法引发的异常。您可能希望仔细查看自己的代码。
您的Await
块正在尝试捕获异常,但在此上下文中不可能。 Exception
由Discovery
actor引发,而不是作为消息发送。问你使用的模式(?)只是等待消息到达。只使用SupervisorStrategy
可以让你回到抛出的异常。您可以向应用程序Guardian actor发送消息,告知初始化失败,以便应用程序退出,而不是升级Supervisor
中的异常。或直接在Supervisor
中进行操作。
import java.util.concurrent.TimeUnit
import akka.actor.SupervisorStrategy.Escalate
import akka.actor._
import akka.pattern.ask
import akka.testkit.{ImplicitSender, TestKit}
import akka.util.Timeout
import org.scalatest.{BeforeAndAfterAll, FunSuiteLike, Matchers}
import scala.concurrent.Await
abstract class ActorSuite(systemName: String)
extends TestKit(ActorSystem(systemName))
with FunSuiteLike
with ImplicitSender
with Matchers
with BeforeAndAfterAll {
override def afterAll {
TestKit.shutdownActorSystem(system)
}
}
class FailingActorInitializationSuite extends ActorSuite("failing-system") {
test("run it") {
val supervisor = system.actorOf(Props[Supervisor])
var discoveryActor: ActorRef = null
implicit val timeout = Timeout(60, TimeUnit.SECONDS)
Await.result(
supervisor ?(Props[Discovery], "Discovery"), timeout.duration) match {
case actor: ActorRef =>
discoveryActor = actor
}
}
}
class Supervisor extends Actor with ActorLogging {
override val supervisorStrategy =
AllForOneStrategy() {
case e: Exception =>
log.error(s"Caught an exception [${e.getCause.getMessage}] and escalating")
Escalate
}
override def receive: Receive = {
case (p: Props, s: String) => sender() ! context.actorOf(p, s)
}
}
class Discovery extends Actor {
override def preStart(): Unit = {
super.preStart()
throw new RuntimeException("Can't create")
}
override def receive: Actor.Receive = {
case _ =>
}
}