Newbie question of Akka - I'm reading over Akka Essentials, could someone please explain the difference between Akka Stop/Poison Pill vs. Kill ? The book offers just a small explaination "Kill is synchronous vs. Poison pill is asynchronous." But in what way? Does the calling actor thread lock during this time? Are the children actors notified during kill, post-stop envoked, etc? Example uses of one concept vs. the other?
Many thanks!
Both stop and PoisonPill will terminate the actor and stop the message queue. They will cause the actor to cease processing messages, send a stop call to all its children, wait for them to terminate, then call its postStop hook. All further messages are sent to the dead letters mailbox.
The difference is in which messages get processed before this sequence starts. In the case of the stop call, the message currently being processed is completed first, with all others discarded. When sending a PoisonPill, this is simply another message in the queue, so the sequence will start when the PoisonPill is received. All messages that are ahead of it in the queue will be processed first.
By contrast, the Kill message causes the actor to throw an ActorKilledException which gets handled using the normal supervisor mechanism. So the behaviour here depends on what you've defined in your supervisor strategy. The default is to stop the actor. But the mailbox persists, so when the actor restarts it will still have the old messages except for the one that caused the failure.
Also see the 'Stopping an Actor', 'Killing an Actor' section in the docs:
http://doc.akka.io/docs/akka/snapshot/scala/actors.html
And more on supervision strategies:
http://doc.akka.io/docs/akka/snapshot/scala/fault-tolerance.html
Use PoisonPill whenever you can. It is put on the mailbox and is consumed like any other message. You can also use "context.stop(self)" from within an actor.
PoisonPill asynchronously stops the actor after it’s done with all messages that were received into mailbox, prior to PoisonPill.
You can use both actor stop and poison pill to stop processing of actors, and kill to terminate the actor in its entirety.
x.stop is a call you make in akka receive method, will only replace actor state with new actor after calling postStop.
x ! PoisonPill is a method that you pass to actor to stop processing when the actor is running(Recommended). will also replace actor state after calling postStop.
x.kill will terminate the actor and will remove the actor in the actor Path and replace the entire actor with a new actor.
Related
I know actors are persistent, They are always alive sitting idle as long as there is nothing to do(no messages in the mailbox), So who monitors the mailbox ?
Is it the Actor itself ? but it doesn't have a thread assigned from dispatcher until its having a message.?
Or, is there any background daemon running monitoring mailboxes of each actors?
As #Sarvesh Kumar Singh mentioned, actor is not by default persistent. You can create persistent actor by extending PersistentActor: Akka Persistence.
In fact, when a actor(cell) is created in the actor system hierarchy, its mailbox(Mailbox is a subclass of Runnable) will be attached to the dispatcher, when the actor is started, the dispatcher will then execute the mailbox runnable(defined in the run method) by polling message from the mailbox queue, if there's a message, it will trigger the defined actor receive method to actually handle the message. Message looping(during this run, the messages in the queue will the be handled into batch, if handling this batch of batch doesn't pass the limit of dispatcher throughput configuration) is also done in the run method by a recursive call of processMailBox defined in mailbox. At the end of each round, the mail box will attach itself to the dispatcher thread pool for execution if there's messages the actor mail box is scheduled for execution the the loop continues. If not, the loop is broken, the next run will be scheduled when there's message sent to the actor, at this moment, message will be dispatched via the dispatcher attached with the actor cell when you call actorRef ! message, this will make the dispatcher to schedule the message handling, check this out: Dispatch::sendMessage and Dispatcher::dispatch. As explained in Dispatchers, dispatcher's throughput can be configured to determine the maximum number of messages to be processed per actor before the thread jumps to the next actor.
do you have any experience with akka actor memory management/leak. Here I have a module use akka actor to communicate with other modules, but as time goes by one of module went down, because of heap memory size.
Is it necessary to send poison pill to children actor after it finished? Because every request in, I'd like to make another actor, each request. Is it necessary to send poison pill again in children actor, if they have their own children actor also?
ps: I'm using Scala Akka
Thanks
Yes, every Actor you create needs to be stopped explicitly. This is typically done by calling context.stop(self) from within the Actor (if it can determine that it is finished with its task) or having the supervisor stop it using context.stop(child).
To prevent running out of memory you can use bounded message queue aka mailbox on the receiving actor: http://doc.akka.io/docs/akka/snapshot/scala/mailboxes.html.
To pick how you want to manage child actors (restart, kill, etc) use supervisor strategy:
http://doc.akka.io/docs/akka/snapshot/general/supervision.html. Supervisor strategy can be picked at any level/parent.
I'm currently sending a message to an Akka actor every second for it to perform a task.
If that task (function) is still running when a new message is received by the actor, I would like the actor to do nothing. Basically, I want the actor function to be run only if it's not already running.
What's a good way to do this? Should I use Akka actors or do it another way?
Cheers
Actors process a message at a time. The situation you describe cannot happen.
Akka actors process their messages asynchronously one-by-one, so you can only drop/ignore "expired" messages to avoid extra processing and OutOfMemoryException-s due to actor's Mailbox overflow.
You can ignore expired (more than 1 second old in your case) messages inside your actor:
case class DoWork(createdTime: Long = System.currentTimeMillis)
final val messageTimeout = 1000L // one second
def receive = {
case DoWork(createdTime) =>
if((System.currentTimeMillis - createdTime) < messageTimeout) { doWork() }
}
Or you can create a custom Mailbox which can drop expired messages internally.
Of course, as Robin Green already mentioned, actors in general are not supposed to run long-running operations internally so this approach can be suitable only if your actor doesn't need to process other kind of messages (they will not be processed in time). And in case of high CPU demands you may consider to move your actor on a separate dispatcher.
Is the following statement correct, otherwise how can it be improved?
When an Akka actor is sent a message, a job is submitted to the executor.
When there is a free thread, it calls the job which obtains a lock on
the actor (assuming it can, otherwise another job is taken). The
receive method of the actor is then called and once it completes,
the job is discarded and the thread returned to the pool. The cycle is then repeated.
All the complicated stuff related to concurrent threads is
handled by Akka, freeing the programmer to concentrate on
solving business problems.
More accurate would be:
When a message is sent to an actor, it is placed in this actor's queue called mailbox. At the same time there can be hundreds or thousands of actors having pending messages in their mailboxes. Akka, using limited number of worker threads, selects a subset of such actors and calls their receive method with each and every message from mailbox in chronological order.
More than one thread never handles the same actor. Also Akka may decide to interrupt processing of messages from a mailbox and select different actor to remain fair and avoid starvation. Because one thread is needed for each receive invocation, this method should never block, wait or sleep.
I'm a newbie to actor model. Could anyone please explain the lifecycle of an actor in actor model? I've been looking for the answer in the documentation, but I couldn't find anything satisfactory.
I'm interested in what an actor does after it completes the onReceive() method - is it still alive or is it dead? Can we control its lifetime to say "don't die, wait there for the next message"? For example, with a round-robin router, if I set it to have 5 actors - would it always distribute the work across the same 5 actors? Or actors are destroyed and created anytime there is a message, but the maximum limit is always 5.
Thanks!
The Actor is always alive unless you explicitly "kill" it (or it crashes somehow). When it receives a message, it will "use" a thread, process the message, then go back to an "idle" state. When it receives another message, it becomes "active" again.
In the case of a round-robin router with 5 Actors, it is the same 5 Actors - the router does not create new ones each time a message is sent to the router.
The Actor model follows an "isolated mutability" (concurrency) model - it encapsulates state only to itself - other Actors are not able to touch this state directly, they can only interact with it via message passing. The Actors must be "alive" in order to keep the state.