Is there a difference between these two? When I do:
context.actorSelection(actorNameString)
I get an ActorSelection reference which I can resolve using the resolveOne and I get back a Future[ActorRef]. But with an actorOf, I get an ActorRef immediately. Is there any other vital differences other than this?
What might be the use cases where in I would like to have the ActorRef wrapped in a Future?
actorOf is used to create new actors by supplying their Props objects.
actorSelection is a "pointer" to a path in actor tree. By using resolveOne you will get actorRef of already existing actor under that path - but that actorRef takes time to resolve, hence the Future.
Here's more detailed explanation:
http://doc.akka.io/docs/akka/snapshot/general/addressing.html
An actor reference designates a single actor and the life-cycle of the reference matches that actor’s life-cycle; an actor path represents a name which may or may not be inhabited by an actor and the path itself does not have a life-cycle, it never becomes invalid. You can create an actor path without creating an actor, but you cannot create an actor reference without creating corresponding actor.
In either processes, there is an associated cost of producing an ActorRef.
Creating user top level actors with system.actorOf cost a lot as it has to deal with error kernel initialization which also cost significantly. Creating ActorRef from child actor is very fair making it suitable for one actor per task design. If in an application, for every request, a new set of actors are created without cleanup, your app may run out of memory although akka actors are cheap. Another good is actorOf is immediate as you mentioned.
In abstract terms, actorSelection with resolveOne looks up the actor tree and produces an actorRef in a future as is not so immediate especially on remote systems. But it enforces re-usability. Futures abstract the waiting time of resolving an ActorRef.
Here is a brief summary of ActorOf vs. ActorSelection; I hope it helps:
https://getakka.net/articles/concepts/addressing.html
Actor references may be looked up using the ActorSystem.ActorSelection
method. The selection can be used for communicating with said actor
and the actor corresponding to the selection is looked up when
delivering each message.
In addition to ActorSystem.actorSelection there is also
ActorContext.ActorSelection, which is available inside any actor as
Context.ActorSelection. This yields an actor selection much like its
twin on ActorSystem, but instead of looking up the path starting from
the root of the actor tree it starts out on the current actor.
Summary: ActorOf vs. ActorSelection
ActorOf only ever creates a new actor, and it creates it as a direct
child of the context on which this method is invoked (which may be any
actor or actor system). ActorSelection only ever looks up existing
actors when messages are delivered, i.e. does not create actors, or
verify existence of actors when the selection is created.
Related
I create an actor A. When I send a message to A, the receive method tries to create an actor B. When I run a piece of code that calls:
context.system.actorOf(Props[B], "B")
I get an exception:
InvalidActorNameException: actor name [B] is not unique!
Do you have any idea why this is happening?
Actor paths (part of which is the name that you pass to system.actorOf or context.actorOf, if you use the variants of actorOf that take a name) must be unique in an actor system. You're probably sending more than one message to actor A: every time actor A receives this message, it tries to create a top-level actor B with the name "B". Either drop the name altogether...
context.system.actorOf(Props[B])
...or add a unique identifier to the name. For example:
val uuid = java.util.UUID.randomUUID.toString
context.system.actorOf(Props[B], s"B-${uuid}")
As a side note, top-level actors (i.e., actors created via system.actorOf) should be made sparingly, as the documentation advises:
Top-level actors are the innermost part of your Error Kernel, so create them sparingly and prefer truly hierarchical systems. This has benefits with respect to fault-handling (both considering the granularity of configuration and the performance) and it also reduces the strain on the guardian actor, which is a single point of contention if over-used.
If your intent is to create an actor B as a child of actor A every time the latter receives a message, then use context.actorOf.
I'm new to akka-actor and confused with some problems:
when I create an actorSystem, and use actorOf(Props(classOf[AX], ...)) to create actor in main method, how many instances are there for my actor AX?
If the answer to Q1 was just one, does this mean whatever data-structure I created in the AX actor class's definition will only appear in one thread and I should not concern about concurrency problems?
What if one of my actor's action (one case in receive method) is a time consuming task and would take quite long time to finish? Will my single Actor instance not responding until it finish that task?
If the answer to Q3 is right, what I am supposed to do to prevent my actor from not responding? Should I start another thread and send another message back to it until finish the task? Is there a best practice there I should follow?
yes, the actor system will only create 1 actor instance for each time you call the 'actorOf' method. However, when using a Router it is possible to create 1 router which spreads the load to any number of actors. So in that case it is possible to construct multiple instances, but 'normally' using actorOf just creates 1 instance.
Yes, within an actor you do not have to worry about concurrency because Akka guarantees that any actor only processes 1 message at the time. You must take care not to somehow mutate the state of the actor from code outside the actor. So whenever exposing the actor state, always do this using an immutable class. Case classes are excellent for this. But also be ware of modifying the actor state when completing a Future from inside the actor. Since the Future runs on it's own thread you could have a concurrency issue when the Future completes and the actor is processing a next message at the same time.
The actor executes on 1 thread at the time, but this might be a different thread each time the actor executes.
Akka is a highly concurrent and distributed framework, everything is asynchronous and non-blocking and you must do the same within your application. Scala and Akka provide several solutions to do this. Whenever you have a time consuming task within an actor you might either delegate the time consuming task to another actor just for this purpose, use Futures or use Scala's 'async/await/blocking'. When using 'blocking' you give a hint to the compiler/runtime a blocking action is done and the runtime might start additional thread to prevent thread starvation. The Scala Concurrent programming book is an excellent guide to learn this stuff. Also look at the concurrent package ScalaDocs and Neophyte's Guide to Scala.
If the actor really has to wait for the time consuming task to complete, then yes, your actor can only respond when that's finished. But this is a very 'request-response' way of thinking. Try to get away from this. The actor could also respond immediately indicating the task has started and send an additional message once the task has been completed.
With time consuming tasks always be sure to use a different threadpool so the ActorSystem will not be blocked because all of it's available threads are used up by time consuming tasks. For Future's you can provide a separate ExecutionContext (do not use the ActorSystem's Dispatch context for this!), but via Akka's configuration you can also configure certain actors to run on a different thread pool.
See 3.
Success!
one instance (if you declare a router in your props then (maybe) more than one)
Yes. This is one of the advantages of actors.
Yes. An Actor will process messages sequentially.
You can use scala.concurrent.Future (do not use actor state in the future) or delegate the work to a child actor (the main actor can manage the state and can respond to messages). Future or child-actor depends on use case.
Akka has deprecated actorFor in favor of actorSelection. The former returns an ActorRef while the latter returns an ActorSelection which could be a collection of ActorRefs.
When migrating from actorFor to actorSelection, you have a couple of optoins:
Option 1: Both ActorSelection and ActorRef have a tell method, so you could almost exchange actorSelection for actorFor (this is not always true - ask is not the same and actorSelection could point to multiple ActorRefs) so long as there is only one actor for that selection and you are only telling the actor.
Option 2: Get an ActorRef from the ActorSelection. This can be done using either Identify (which involves a couple more messages) or resolveOne (which involves a Future).
In Option 1, what kind of overhead does ActorSelection add compared to the ActorRef from actorFor?
Is there a better option than the ones listed above?
There is overhead for using ActorSelection versus ActorRef, specifically:
It is not as performant as with ActorRef, since it has to traverse the
hierarchy of actors in the path. If you use remote sends the actor
selection traversal will unlikely be the bottleneck, but you have to
verify that for your specific usage. We optimized ActorSelection in
2.3.x, so it will be faster when you update to that version.
Source: Post by Patrik Nordwall on the Akka User list.
In the option 1, the overhead is that the message might be sent to multiple actors instead of just one. If you use wildcards, the actor system will have to identify all the actors matching the actor selection string (some of which are possibly remote), so this might end up being a slower than sending a message to just one specific actor.
However, as long as you don't use wildcards with actorSelection, the ActorSelection object will refer to at most one actor.
If you want to use the ask pattern, you have to first obtain the ActorRef using the Identify message - there is no better way that option 2.
Confirming that every time you call Akka.system.actorOf or Akka.system.scheduler it'll create a new ActorSystem in the application? Looking at some code where it calls Akka.system.actorOf every time it has to create a new actor, which I think should have been context.actorOf to use the existing ActorSystem (which should have been created at the app startup). Is my understanding correct that calling Akka.system.actorOf every single time, to create a new actor, is very wrong?
You create new ActorSystem only when you call ActorSystem.apply method:
val system = ActorSystem("YourApplication")
Of course, when you call methods on the system you do not create new systems, that is, the following:
val actor = system.actorOf(Props[SomeActor], "someActor")
won't create new system, it will just create new top-level actor in the system. You usually call system.actorOf method when you are outside of an actor, for example, in initialization code when there are no actors created yet.
context, on the other hand, is a way to interact with the system from inside an actor. context is a member of Actor trait, which is inherited into your actors. You use context to access actor system's scheduler, to watch actors, to create child actors, to change actor's behavior etc. context.actorOf will create child actor.
So no, calling system.actorOf for creating actors is absolutely not wrong. You just have to keep in mind that when you use system.actorOf you're creating top-level actors, and that's not something you need always. Usually you create one or several top-level actors, which then in turn create child actors and so on.
According to the docs:
Using the ActorSystem will create top-level actors, supervised by the
actor system’s provided guardian actor, while using an actor’s context
will create a child actor.
So basically, it depends on what you want to achieve.
More details here.
EDIT:
Concerning your concrete question (I am sorry, I misunderstood you), you should see an ActorSystem as a heavyweight structure that will allocate up to N threads, and each Actor will run within one of these threads (the key point here is that there is no mutable state). ActorSystems share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. They are also the entry point for creating or looking up actors.
Creating an ActorSystem is very expensive, so you want to avoid creating a new one each time you need it. Also your actors should run in the same ActorSystem, unless there is a good reason for them not to. The name of the ActorSystem is also part the the path to the actors that run in it.
There is no Akka.system.actorOf method in the current API. Normally you hold a reference to the application ActorSystem as others already showed you, and create child actors from that context:
val system = akka.actor.ActorSystem("YourApplication");
val actor1 = system.actorOf(Props[Actor1], "Actor1")
val actor2 = system.actorOf(Props[Actor2], "Actor2")
So, in short, I have never tried it but I assume every call to akka.actor.ActorSystem will try to create a new ActorSystem and it would probably fail if no different ActorSystem names/configurations are provided.
You can only have one ActorSystem in a Cluster. thats why you cant use new.
Something very similar to main..
trying to learn by answering to it.
Akka 2.x requires many commands to reference an ActorSystem. So, to create an instance of an actor MyActor you might say:
val system = ActorSystem()
val myActor = system.actorOf(Props[MyActor])
Because of the frequent need for an ActorSystem: many code examples omit the creation from the code and assume that the reader knows where a system variable has come from.
If your code produces actors in different places, you could duplicate this code, possibly creating additional ActorSystem instances, or you could try to share the same ActorSystem instance by referring to some global or by passing the ActorSystem around.
The Akka documentation provides a general overview of systems of actors under the heading 'Actor Systems', and there is documentation of the ActorSystem class. But neither of these help a great deal in explaining why a user of Akka can't just rely on Akka to manage this under-the-hood.
Question(s)
What are the implications of sharing the same ActorSystem object or creating a new one each time?
What are the best practices here? Passing around an ActorSystem all the time seems surprisingly heavy-handed.
Some examples give the ActorSystem a name: ActorSystem("MySystem") others just call ActorSystem(). What difference does this make, and what if you use the same name twice?
Does akka-testkit require that you share a common ActorSystem with the one you pass to the TestKit constructor?
Creating an ActorSystem is very expensive, so you want to avoid creating a new one each time you need it. Also your actors should run in the same ActorSystem, unless there is a good reason for them not to. The name of the ActorSystem is also part the the path to the actors that run in it. E.g. if you create an actor in a system named MySystem it will have a path like akka://MySystem/user/$a. If you are in an actor context, you always have a reference to the ActorSystem. In an Actor you can call context.system. I don't know what akka-testkit expects, but you could take a look at the akka tests.
So to sum it up, you should always use the same system, unless there is a good reason not to do so.
Here are some materials which might be helpful to understand "Why does document always suggest to use one ActorSystem for one logical application" :
The heaviest part of an ActorSystem is the dispatcher. Each ActorSystem has at least one. The dispatcher is the engine that makes the actors running. In order to make running, it needs threads (usually got from a thread pool). The default dispatcher uses a fork-join thread pool with at least 8 threads.
There are shared facilities, like the guardian actors, the event stream, the scheduler, etc. Some of them are in user space, some are internal. All of them need to be created and started.
One ActorSystem with one thread pool configures to the numbers of cores should give the best results in most cases.
Here document mentions logical application, I prefer to consider blocking or non-blocking application. According to dispatcher's configuration, one ActorSystem is for one configuration. If the application is for the same logics, one ActorSystem should be enough.
Here is a discussion , if you have time, you can read it. They discuss a lot, ActorSystem, local or remote, etc.