Akka Ops: Create, Send, Become, Supervise
Table of Contents
This is part of Akka Actors with Scala. Understanding all that is here is spiral-like. Do read these notes first. Secondly, TypeSafe Activator: Akka Get Started. Third, to better understand, read the details given in Akka Examples (perhaps skipping the Documentation).
1 Akka Actors
- Akka Actors: Extremely lightweight (> 2.7 million actors per GB
RAM)
import akka.actor._
- Messages are the "kinetic energy" in an actor system.
- Actors can have lots of buffered "potential energy", but cannot do anything with it until triggered by a message.
- Everything is asynchronous and lockless.
1.1 Example Actor
case class Greeting (who: String) class GreetingActor extends Actor { def receive = { case Greeting(who) => sender ! (s"Hello, $who! Thanks.") } }
2 Akka Actors "Systems"
- Allocate (internal) threads:
ActorSystem acsywsu = ActorSystem.create("WSU-CEG-7370-Actors");
- Allocate (internal) threads:
ActorSystem acsyiiitd = ActorSystem.create("IIID-5xx-DIC-Actors");
Several actor systems, possibly with different configurations, can co-exist.
val grtr = acsyiiitd . actorOf(Props[GreetingActor], "greeter") grtr ! Greeting("Brad Pitt")
Props
is a configuration class to specify options for the creation of actors.- Try the above in scala REPL. You need the import shown below.
import akka.actor.{ ActorRef, ActorSystem, Props, Actor }
- glitch: akka://WSU-CEG-7370-Actors/deadLetters
3 An Actor in Java
Akka actors are do-able in Java. Much longer.
public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } }
- Continued …
3.1 An Actor in Java, contd-1
public class GreetingActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); public void onReceive(Object message) throws Exception { if (message instanceof Greeting) getSender.tell("Hello " + ((Greeting) message).who + " Thanks."); } }
- Continued …
3.2 An Actor in Java, contd-2
ActorSystem acsy = ActorSystem.create("WSU-CEG-7370-Actors"); ActorRef grtr = acsy . actorOf( new Props(GreetingActor.class), "greeter"); grtr.tell(new Greeting("Brad Pitt"));
4 Create an Actor
- Create an actor by
calling
ActorContext.spawn()
. The creator actor becomes the parent of the newly created child actor. - Akka Actor receive message loop is exhaustive, different from Erlang and the late Scala "native" Actors.
- Provide a pattern match for all messages that the actor can accept.
- To handle unknown messages have a default case
case _ => ...
- Killing an Actor:
victim ! Kill
context.system.shutdown()
the ActorSystem when everything’s finished
5 Actor Lifecycle
Figure 1: Actor Lifecycle
6 Actor Op: Send
- The method named
receive
defines how messages are handled. - The Bang
!
akatell
. - Asynchronous and Non-blocking – "Fire-forget"
- Order of send == order of arrival in the mailbox of receiving actor. Message ordering is guaranteed on a per-sender basis.
- The size of the mailbox can be bounded (cf Actor Std Model) or unbounded.
def ! (message: Any)
(implicit sender: ActorRef = Actor.noSender)
- The Query
?
sends a message asynchronously and returns aFuture
representing a possible reply. Akaask
.
7 Actor Op: Become
- Behaviors can be pushed and popped
context.become
Replaces the current (the top of the behavior stack) behavior- Will now react according to the new behavior to the messages
context.unbecome
pop the stack
7.1 Example: HotSwapActor
import akka.actor._ class HotSwapActor extends Actor { import context._ def angry: Receive = { case "ang" => sender ! "I am already angry >:(" case "hap" => become(happy) } def happy: Receive = { case "hap" => sender ! "I am already happy :-)" case "ang" => become(angry) } def receive = { case "ang" => become(angry) case "hap" => become(happy) } }
7.2 Become – Why?
- Implement finite state machines
import akka.actor.FSM
- Spawn up an empty generic worker actor that can become whatever the master needs
- Let a highly contended actor adaptively transform into an actor pool or a Router
- Implement graceful degradation
7.3 Finite State Machines, and P3
- http://www.typesafe.com/activator/template/akka-sample-fsm-scala
- ./dining-philosophers-akka-fsm.html
- IIITD DIC (WSU CEG 7370) P3: Understand the example above, and answer the questions.
7.4 Add to the Stack, Not Replace
import akka.event.Logging; import akka.actor._ case object Swap class Swapper extends Actor { import context._ val log = Logging(system, this) def receive = { case Swap => log.info("Hi") become({ case Swap => log.info("Ho") unbecome() /* just for fun */ }, discardOld = false) /* not replace */ }} object SwapperApp extends App { val sys = ActorSystem("SwapperSystem") val a = sys.actorOf(Props[Swapper], name="swapper") // alternately logs Hi, Ho, ... a!Swap; a!Swap; a!Swap; a!Swap; a!Swap; a!Swap }
8 Actor Op [Hidden]: Supervise
- "Let it crash!"
- When an actor crashes, its parent can either
restart
,stop
it, orescalate
the failure, up the hierarchy of actors. - A chain of responsibility, all the way to the top.
- When an actor crashes, its parent can either
- Every single Akka actor has a default supervisor strategy. Which is usually sufficient. But it can be overridden.
- Provides clean separation of business logic and error handling
- Traditional failure management:
- You are given a single thread of control
- Need to do all explicit error handling WITHIN this single thread
- Errors do not propagate between threads
- Leads to defensive programming, with error handling tangled with business logic
9 DeathWatch
Register to receive
Terminated
message provided by theDeathWatch
component of the Akka actor system.import akka.actor.{ Actor, Props, Terminated } class WatchActor extends Actor { val child = context.actorOf(Props.empty, "child") context.watch(child) // registration var lastSender = system.deadLetters def receive = { case "kill" => context.stop(child); lastSender = sender() case Terminated(`child`) => lastSender ! "finished" } }
- Note the back-quotes in
Terminated(`child`)
10 References
- Akka Documentation https://doc.akka.io/docs/akka/current/ Nearly all the code snippets and figures are from here. Reference.
- Jonas Boner, "Above the Clouds: Introducing Akka", 2011. Web search. Video or pdf. Highly recommended.