Let it Crash
We don't want to just graft recovery code into the operational flow, so catching the exception inside an actor where the business logic resides is not an option. Instead of using one flow to handle both normal code and recovery code. Akka provides two separate flows: The normal flow consists of actors that handle normal messages; the recovery flow consists of actors that monitor the actors in the normal flow. Actors that monitor other actors are called supervisors.
Akka has chosen to enforce parental supervison, any actor that creates actors automatically becomes the supervisor of those actors. A supervisor doesn't "catch exceptions", rather it decides what should happen with the crashed actors that it supervises based on the cause of the crash.
Actor Lifecycle
Restart - The actor must be recreated from its Props, and use the same ActorRef.
Resume - Th same actor instance continues, the crash is ignored.
Stop - The actor must be terminated.
Escalate - The supervisor escalates the problem to its parent.
When the actor is in a Started state, it can be restarted to reset the internal state of the actor. The actor instance is replaced by a fresh actor instance.
After the instance is created, the actor is going to be started by Akka. The preStart hook is called just before the actor is started. This hook can be used to set the initial state of the actor.
The postStop hook is called just before the actor is terminated. This hook implements the opposite function of the preStart and releases resources created in the preStart method, and possibly stores the last state of the actor. After the actor is stopped, the ActorRef is redirected to the deadLetters ActorRef of the actor system.
When a restart occurs, the preRestart method of the crashed actor instance is called. After the preRestart hook is called, a new instance of the actor class is created and therefore the constructor of the actor is executed, through the Props object. ActorRef will continue to live on after the restart: the actor instance has not been terminated but replaced by a new one.
The fresh actor instance, during restart, is connected to the same ActorRef the crashed actor was using before the fault. The preRestart method takes two arguments: the reason for the restart and optionally the message that was being processed when the actor crashed.
The super implementation of the postRestart is called because this will trigger the preStart function by default. The preStart and postStop are called by default during a restart.
class DbSupervisor(writerProps: Props) extends Actor { val writer = context.actorOf(writerProps) } class LogProcessor(dbSupervisor: ActorRef) extends Actor { def receive = { case LogFile(file) => parse(file).foreach(dbSupervisor ! _) } } object LogProcessApp extends App { val writerProps = Props(new DbWriter(con)) val dbSuperProps = Props(new DbSupervisor(writerProps)) system.actorOf(dbSuperProps) }
Future
Futures are the tool to use when you would rather use functions and don't want or need to keep any state to do the job. The java.util.concurrent.Future class requires polling and only provides a way to get to the result with a blocking get() method, whereas the Scala future makes it possible to combine function results without blocking or polling.
The code block provided to the Future.apply method is passed by name. A pass-by-name argument only gets evaluated the first time it's referenced inside the function. In the case of Future, it's evaluated on another thread. You should always use immutable data structures when working with futures.
Promise
If you can simply use APIs that return Future, then you probably won't run into Promise[T] very often. Promise[T] wraps an existing multithreaded callback-style API into an API that returns Future[T].
Akka Remote
Aka provides two ways to get a reference to an actor on a remote node. One is to look up the actor by its path; the other is to create the actor, get its reference, and deploy it remotely.
Think of the actorSelection method as a query in the actor hierarchy.
Aka uses java serialization by default for any message that needs to be sent across the wire.
Remote actors couldn't be watched for termination like local actors.
The ActorRef to a remote actor is retrieved using a special Identify message that's sent to the ActorSelection.
No comments:
Post a Comment