This is a note for the book Akka in Action.
Fault Tolerance
Exception handling doesn’t solve the need to put a fault into its right handler – it mostly used to keep consistent state, not recovery from failures. Adding recovery code in exception handler is not a good idea because often it is a cross-cutting concern. Akka provides the following fault tolerance features in a way of eparation of concerns:
- Fault containment/isolation in a defined structure.
- Redundancy
- Replacement
- Reboot
- Component lifecycle
- Suspend with calls saved
Exception handling cannot do it well:
- re-creating/replacing objects and their dependencies is hard.
- ojbects communicates with each other via direct all, not easy to isolate them.
- Fault-recovery code and functional code are tangled up.
Akka provides two separate flows: one for normal logic and one for fault recovery logic. The normal actor code for handling messages only process normal logic without error handling or fault recovery logic. It creashes when there is an exception and its mailbox is suspended until its supervisor decides what to do with the exception. A supervisor decide what to do based on the cause of the crash: restart, resume, stop, and escalate.
An actor is created and automatically started with the actorOf
method in ActorSystem
or an actor’s ActorContext
. There is a preStart
hook. An actor can be stopped using the stop
method or by sending a PoisonPill
message. It has a postStop
hook. A stopped actor is disconnected from its ActorRef
and its ActorRef
is redirected to the deadLettersActorRef
.
In restart, an instance of an actor is replaced. The old crashed instance uses the preRestart
hook, the new instance uses the postRestart
hook. The default implementation of the preRestart
stops all child actors and calls the postStop
hook. A crashed actor instance in a restart doesn’t send a Terminated
message ot its supervisor. The new replacing actor use the same ActorRef
as the crashed actor. The supervisor decides what should be stored to enable state restoration in restarting.
Any actor can watch an actor and receive Terminated
message. Only parent actor can supervise its child actors. The strategy can be OneForOneStrategy
or AllForOneStrategy
. Strategy types can be Stop
, Restart
, Resume
, or Escalate
.
The default strategy is to stop on initialization and killed exception, restart on all other exceptions. Any Throwable
that isn’t handled by the supervisor strategy will be escalated to the parent of the supervisor.
Futures
Futures are used to combine asynchronous functions without states. Actors are great for reactive state management based on messages. Actors live on for a long time and can be supervised and monitored.
A future holds future result and is an asynchronous result handler. After completion, the read-only result can be read many times. Futures are handy for pipelining.