Domanda

So this question is related to an old one of mine: Do I need to re-use the same Akka ActorSystem or can I just create one every time I need one?

I asked a question about the lifecycle of actors, and I knew something was wrong in my mind, but couldn't phrase it correctly. Hopefully I can now :-).

Here's the situation. I want to test actors that have dependencies to other components and actors, so I went about composing my actors in bootstrap time (I'm using scalatra but however you bootstrap your app). I therefore have something like this:

trait DependencyComponent 
{
 val dependency : Dependency
}

trait ActorComponentA extends Actor with DependencyComponent {
   val actorB : ActorRef
} 

trait ActorComponentB extends Actor with DependencyComponent  

Ok, so now I can test my actors by extending the traits and providing mock dependencies, all good. And I can bootstrap my app like so:

Bootstrap

val system = ActorSystem()
val actorA = system.actorOf(Props[DefaultActorA])

class DefaultActorB extends ActorComponentB {   
   val dependency = new RealDependency() 
}

class DefaultActorA extends ActorComponentA {   
  val dependency = new RealDependency()   
  val actorB = context.actorOf(Props[DefaultActorB]).withRouter(RoundRobinRouter(nrOfInstances = 100))) 
}

Cool, Im happy :-), now I can use the actorSystem and actorA within my app, and it has a 100 actorB routed to pass work to. So when actorA decideds that the work is done, it's my understanding that it should broadcast to the routed actors to shutdown. At this point when another request comes in actorA can no longer send messages to the router because all its actors are dead.

If I wasn't setting this up at boot time then actorA and its dependencies could be created when needed in my app. But that is very much like "newing up on object" in DI world. In order to test I would end up overriding the places where the actors were created.

Scalatra docs are suggesting creating my actors at boot time, so I feel that I am missing somehting here. Any help appreciated.

Cheers, Chris.

EDIT

I've +1 both @futurechimp and @cmbaxter as these both seem valid but slightly conflicting. So this is an open comment to both of you.

So @cmbaxter am I right in thinking that your suggesting never calling 'stop' on the routed actors and just maintaining a pool of them for use by ALL requests. And @futurechimp, your suggesting having the servlet instantiate the actors per request and killing them at the end of there lifecycle. Right?

It seems like per-request will spawn more actors (but dispose of them). Where the poll will have only a limited set for all requests in which case is there a potential bottle neck to this approach?

I guess basically, I'm asking if my assumptions are correct and if so what are the advantage and disadvantages to both approaches?

È stato utile?

Soluzione

Instantiating an ActorSystem is expensive - however instantiating an Actor isn't. If you only want to instantiate your ActorSystem in ScalatraBootstrap, and your Actors elsewhere, that should work fine if that's what you need to do. I'll talk to some other people to confirm this, and then change the docs in Scalatra's Akka Guide to avoid confusion in future.

Altri suggerimenti

One of the questions you have to ask yourself here is: Are my actors going to be stateful or stateless. If stateless (and I would prefer this approach personally when possible), then they can be "long-lived" and you can start them when the server boots up and leave them running for the duration of the server's life. When you need to talk to them from elsewhere in the code, use system.actorFor(String) or system.actorSelection(String) (depending on what version of akka you are using) to look up the actor and send it a message. If the actors are going to be stateful, then they probably should be "short-lived" and started up in response to an individual request. In this case, you will not start them up when the server boots up; you will only start up the ActorSystem itself. Then, when the request comes in, you will instantiate via system.actorOf instead and make sure that when the work is done that you stop ActorA as it's the supervisor of all the ActorBs and stopping A will stop all of the Bs started by A.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top