加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

斯卡拉 – 当失败时,谁的责任是创造Akka演员的孩子?

发布时间:2020-12-16 19:14:01 所属栏目:安全 来源:网络整理
导读: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. 一个误导性的引述说: Resu
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.

一个误导性的引述说:

Resuming an actor resumes all its subordinates,restarting an actor
entails restarting all its subordinates,similarly terminating an actor will also terminate all its subordinates

我怀疑我们有责任在preStart方法中创建child(ren),因为Akka的术语RESTART不是reSTART,除非你在它们的父preStart()方法中递归地和显式地创建子节点.

示例(使用Akka 2.0& 2.2-SNAPSHOT):无论我尝试什么,孩子总是刚刚停止,从未在此测试用例中重新启动.我创建了Supervisor – >首先 – >第二关系并在主管中抛出异常.发生的事情是主管重新启动并且First&第二次停了.

test("restart test") {
    val system = ActorSystem("test")
    val supervisor = system.actorOf(Props(new Supervisor),"supervisor")
    supervisor ! CREATE(Props(new First),"first")
    Thread.sleep(500)

    val first = system.actorFor("akka://test/user/supervisor/first")
    first ! CREATE(Props(new Second),"second")
    Thread.sleep(500)
    supervisor ! WTF

    Thread.sleep(20000)
  }

  case object WTF
  case class CREATE(p: Props,name: String)

  class Supervisor extends Actor {
    override val supervisorStrategy =
      OneForOneStrategy(maxNrOfRetries = 10) {
        case _: IllegalStateException       => Restart
        case _: IllegalArgumentException    => Stop
        case _: Exception                   => Restart
    }
    override def preStart() {
      println(s"$self starts")
    }
    override def postStop() {
      println(s"$self stopped")
    }
    override def receive = {
      case WTF => println("throwing exception"); throw new IllegalStateException()
      case CREATE(p,name) => context.actorOf(p,name)
    }
  }
  class First extends Actor {
    override def preStart() {
      println(s"$self starts")
    }
    override def postStop() {
      println(s"$self stopped")
    }
    override def receive = {
      case WTF => println("throwing exception"); throw new IllegalStateException()
      case CREATE(p,name)
    }
  }
  class Second extends Actor {
    override def preStart() {
      println(s"$self starts")
    }
    override def postStop() {
      println(s"$self stopped")
    }
    override def receive = {
      case WTF => println("throwing exception"); throw new IllegalStateException()
      case CREATE => sender ! "ok"
    }
  }

Actor[akka://test/user/supervisor#1599926629] starts
Actor[akka://test/user/supervisor/first#2012011668] starts
Actor[akka://test/user/supervisor/first/second#1750038710] starts

throwing exception Actor[akka://test/user/supervisor#1599926629]
stopped [ERROR] [06/26/2013 11:11:16.899]
[test-akka.actor.default-dispatcher-4] [akka://test/user/supervisor]
null java.lang.IllegalStateException at
com.fg.mail.smtp.IntegrationSuite$Supervisor$$anonfun$receive$1.applyOrElse(IntegrationSuite.scala:40)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:498) at
akka.actor.ActorCell.invoke(ActorCell.scala:456) at
akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237) at
akka.dispatch.Mailbox.run(Mailbox.scala:219) at
akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386)
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)

Actor[akka://test/user/supervisor/first/second#1750038710] stopped
Actor[akka://test/user/supervisor/first#2012011668] stopped
Actor[akka://test/user/supervisor#1599926629] starts

解决方法

你的怀疑是正确的.如果仔细查看 http://doc.akka.io/docs/akka/snapshot/general/supervision.html上重启过程的7步说明,您将看到:

2 . … defaults to sending termination requests to all children …

6 . send restart request to all children which were not killed

因此,您需要覆盖父级的preRestart挂钩以阻止Akka杀死子级,或者覆盖postRestart以重新创建刚刚被杀死的所有子级.

您选择哪个取决于您的应用程序的语义.有时,杀死整个层次结构并以空白板块开始是有用的,有时候不是.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读