2

我有一个监督 Akka 演员,它使用路由器将消息转发给工作演员。

我有一个包装主管的类,当我在该类上调用一个方法时,它“要求”主管做某事,然后我Await.result(theFuture)用来等待结果(没有结果我无法继续)。

如果工作人员抛出异常,我想重新启动抛出异常的工作人员,并且我希望调用包装类的代码捕获异常。

我将 a 传递OneForOneStrategy给路由器构造函数,它RESTART在 a 的情况下返回Exception。在postRestartworker的方法中,我记录了重启,所以我可以验证worker是否真的被重启了。

当工作人员抛出异常时,它会重新启动,但异常会消失。这Future是询问主管的结果,包含一个异常,但它是 a akka.pattern.AskTimeoutException,仅在 5 秒而不是 20 秒后抛出,这是我一直徘徊的隐式超时。异常实际上在工作程序启动后不到一秒发生。

问题 1:如何从调用我的包装类的代码中的工作人员那里获取异常?

另外,worker的receive方法是这样的:

def receive = {
    case r: Request => 
        val response = ??? //throws an exception sometimes
        sender ! response
}

有些东西正在将异常记录到控制台,但这不是我的代码。堆栈跟踪是:

[ERROR] [02/11/2013 21:34:20.093] [MySystem-akka.actor.default-dispatcher-9]  
[akka://MySystem/user/MySupervisor/MyRouter/$a] Something went wrong!
    at myApp.Worker.$$anonfun$receive$1.applyOrElse(Source.scala:169)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
at akka.actor.ActorCell.invoke(ActorCell.scala:386)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
at akka.dispatch.Mailbox.run(Mailbox.scala:212)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:502)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

第 169行是上面方法列表中显示Source.scala的行。val response = ???receive

问题 2:谁将该异常记录到控制台,我该如何阻止它?

4

2 回答 2

3

1)

try somethingThatCanFail() catch {
    case e: Exception => sender ! Status.Failure(e); throw e
}

“告诉失败”会导致调用者获得包含异常的失败。投掷“e”会导致调用 oneForOneStrategy 重新启动工作程序。

2)

记录故障的是参与者系统本身,唯一让它安静下来的方法是通过创建和配置您自己的 LoggingAdapter 来过滤掉事情,如此处所述 http://doc.akka.io/docs/akka/2.1。 0/scala/logging.html有一张票可以改变这个 https://www.assembla.com/spaces/akka/tickets/2824但它是针对 Akka 2.2

由https://groups.google.com/forum/#!topic/akka-user/fenCvYu3HYE回答

于 2013-02-15T18:08:56.357 回答
0

为了收到您的孩子失败的通知,您需要

  • 首先watch是孩子
  • 然后,当演员死亡时,您将收到一个Terminated()对它的引用。

就像是:

class ParentActor extends Actor {
   // this is sample of how to watch for death of one of your children 
   val childActor = context.actorOf(Props[SomeService], "SomeService")
   val dyingChild = context.watch(context.actorOf(childActor))

   def receive = {
     case Terminated(`dyingChild`) =>
        println("dyingChild died") 
     case Terminated(terminatedActor) => 
        println(s"This child just died $terminatedActor")
   }
 }

希望这可以帮助。

于 2013-02-14T01:25:20.793 回答