简体   繁体   English

如何在单例ActorSystem中管理Actor关闭

[英]How to manage actor shutdown in a singleton ActorSystem

I have a singleton actor system in my application, and this works perfectly fine except that when the same application is loaded and unloaded inside the same JVM for testing, I have an error because I try, in my startup procedure, to recreate an actor which already exists. 我的应用程序中有一个singleton actor系统,除了在同一个JVM内加载和卸载同一应用程序进行测试时,它工作正常,但出现错误,因为我在启动过程中尝试重新创建一个actor。已经存在。

As a result I get an akka.actor.InvalidActorNameException because the Actor name is not unique. 结果,我得到akka.actor.InvalidActorNameException因为Actor名称不是唯一的。

I am looking for a way to smoothly shutdown the actors depending on the actor systems without shutting down the actor system itself. 我正在寻找一种方法,可以根据角色系统平稳地关闭角色,而不关闭角色系统本身。 Which is a reasonable strategy for that? 哪个是合理的策略?

This is not exactly answer to your question - " ... a way to smoothly shutdown the actors ... ", but you mentioned that you are able to able to start two applicatons in same JVM. 这不是您问题的完全答案-“ ...一种平稳关闭actor的方法... ”,但是您提到您能够在同一JVM中启动两个应用程序。

Could you make your actor system to be singleton within application instance instead of singleton within whole JVM? 您能否使actor系统在应用程序实例中成为单例,而不是在整个JVM中成为单例?

You would have two independent actor systems, you won't have name conflicts and won't have to start/stop specific actors. 您将有两个独立的演员系统,不会有名称冲突,也不必启动/停止特定演员。

I guess problems could be if some of actors are interacting with outside world, for example consuming some messages from JMS etc. Then it would not be obvious which actor system is processing them. 我想问题可能出在某些参与者正在与外界进行交互,例如使用来自JMS的消息等。那么,不清楚哪个参与者系统正在处理它们。

Do you want somethings like this ? 你想要这样的东西吗?

object AkkaTest extends App {
  import akka.actor._
  import akka.pattern.ask
  import akka.util.Timeout
  import scala.concurrent.duration._

  val system = ActorSystem.create

  val supervisor = system.actorOf(Props[MasterOfPuppets], name = "masterOfPuppets")

  private object AllTerminated

  private class MasterOfPuppets extends Actor {

    var supervised = 0

    var waiterForTerminated: Option[ActorRef] = None

    def receive = {
      case actor: ActorRef =>
        context.watch(actor)
        supervised += 1
      case Terminated(dead) =>
        supervised -= 1
        if (supervised == 0) {
          waiterForTerminated.map(_ ! AllTerminated)
          waiterForTerminated = None
        }
      case AllTerminated =>
        if (supervised == 0) {
          sender ! AllTerminated
        } else {
          waiterForTerminated = Some(sender)
        }
    }
  }

  private class TestedActor extends Actor {
    def receive = {
      case a: Any => sender ! a
    }
  }

  implicit val timeout = Timeout(5.seconds) // needed for `?` below

  // Create first actor
  val actor1 = system.actorOf(Props[TestedActor], name = "name1")
  supervisor ! actor1
  actor1 ! PoisonPill

  val waitForIt = supervisor ? AllTerminated
  Await.result(waitForIt, 5.seconds)
  // Same name
  val actor2 = system.actorOf(Props[TestedActor], name = "name1")
  supervisor ! actor2

  println("ok then")
}

Your problem is very simple : Akka and message are asynchronous. 您的问题很简单:Akka和消息是异步的。 If you try to create an actor just after you kill him, the name is not available. 如果您在杀死演员后立即尝试创建演员,则该名称不可用。 Try just a Thread.sleep before creating new actor and it will work.. :) 在创建新的actor之前,仅尝试Thread.sleep即可,.. :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM