How to manage actor shutdown in a singleton ActorSystem

橙三吉。 提交于 2019-12-24 19:05:49

问题


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.

As a result I get an akka.actor.InvalidActorNameException because the Actor name is not unique.

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?


回答1:


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.

Could you make your actor system to be singleton within application instance instead of singleton within whole 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.




回答2:


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. 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.. :)



来源:https://stackoverflow.com/questions/14808752/how-to-manage-actor-shutdown-in-a-singleton-actorsystem

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!