It’s hard tobuild systems
that are
highlyconcurrent
middleware for building awesome concurrent and distributed applications
Akka
Simpler
Actorsobjects that send and receive messages
STMtransactions in shared memory
Dataflowdeterministic directed flow of data
Actor Model
A Universal Modular ACTOR Formalismfor Artificial Intelligence
Carl Hewitt, Peter Bishop, Richard Steiger
1973
Actor Model
A Universal Modular ACTOR Formalismfor Artificial Intelligence
Carl Hewitt, Peter Bishop, Richard Steiger
1973
Actor Model
A Universal Modular ACTOR Formalismfor Artificial Intelligence
Carl Hewitt, Peter Bishop, Richard Steiger
1973
Actor Model
Physics
Functional programmingfrom Lisp
Message passingfrom Simula and Smalltalk
It’s actors all the way down
Until you reach turtles
What is an actor?
An actor is a computational entity
that responds to messages
sendsend messages to other actors
createcreate new actors
becomedefine behaviour for the next message
Akka Actors
actorOf[SomeActor](“name”)
returns an ActorRef, not an Actor
Actor reference
actor ! message
asynchronous, fire and forget
Send
actor tell message
non-symbolic method name
Send
def receive = { case i: Int => ... case s: String => ... case _ => ...}
match with a partial function
Receive
class Counter extends Actor { var count = 0
def receive = { case Tick => count += 1 }}
Receive
sender ! message
reference to the sender
Reply
class Counter extends Actor { var count = 0
def receive = { case Tick => count += 1 case Get => sender ! count }}
Reply
class Counter extends Actor { var count = 0
def receive = { case Tick => count += 1 case SendTo(actor) => actor ! count }}
pass actor references in messages
Actor-passing
become { case Message => ...}
define the next receive behaviour
Hot swap
unbecome()
revert to the previous behaviour
Hot swap
class Counter extends Actor { def receive = count(0)
def count(i: Int): Receive = { case Tick => become(count(i + 1)) case Get => sender ! i }}
recursive behaviour containing state
Behaviour and state
Example
Async work
HTTP request,received by a front end,
given to a worker,response to the client
class Worker extends Actor { def receive = { case Work(args) => val result = perform(args) sender ! result }}
worker simply replies with a result
Worker
class FrontEnd extends Actor { def receive = { case Request(params) => val worker: ActorRef = ... worker ! Work(params) // response? }}
how is the response handled?
Front end
front end actor receives request
Async workfront end worker
request
create an actor to handle this response
Async workfront end worker
request
responder
send work with reply-to as responder
Async workfront end worker
responder
result through responder
Async workfront end worker
responder
response
class Responder(request: Request) extends Actor { def receive = { case result => request completeWith result self.stop() }}
one-off actor for handling the result
Responder
class FrontEnd extends Actor { def receive = { case Request(params) => val worker: ActorRef = ... implicit val replyTo = context.actorOf(new Responder(request)) worker ! Work(params) }}
create a responder to handle the result
Front end
Futures
val future = actor ? message
ask an actor for something
Ask
val future = actor ask message
non-symbolic method name
Ask
future.get
blocks while waiting for the result
Future
future onComplete { _.value.get match { case Left(problem) => ... case Right(result) => ... }}
add an on-complete callback
onComplete
future onResult { ... }
future onException { ... }
future onTimeout { ... }
three types of completion
Callbacks
val f1 = Future { “hello” }
val f2 = f1 map { _.length }
transform in the future
Mapping
val f = for { a <- Future(40) b <- Future(2)} yield a + b
compose with for comprehensions
Composing
val x, y, z = Promise[Int]()
flow { z << x() + y()}
flow { x << 40 }flow { y << 2 }
compose with dataflow
Dataflow
STM
def transfer(from: Ref[Int], to: Ref[Int], amount: Int) = atomic { from alter (_ - amount) to alter (_ + amount) }
classic bank account example
STM
atomic { if (from.get < amount) retry from alter (_ - amount) to alter (_ + amount)}
explicitly retrying for conditions
STM retry
atomic { // ... deferred { launcher ! FireMissiles }}
callback run when successful
Side-effects
Actor tree
b
a
d
c
ef
g
path to actor c is /a/b/c
Actor path
b
a
d
c
ef
g
system.actorFor(“/a/b/c”)
find an actor using its path
Find actors
Supervision
Erlang’s
9 nines
the parent actor supervises the child
Supervisor
resumeignore and continue as normal
restartcreate a fresh instance
stopterminate the actor permanently
escalatelet the supervisor above decide
case _: ArithmeticException => Resumecase _: ActorInitException => Stopcase _: Exception => Restartcase _ => Escalate
Throwable => Action
Fault handler
only the child that fails is affected
One for One
one child fails, all children are affected
All for One
entire sub-tree is affected
Escalate
top-level guardians isolate and protect
Guardians
user system temp
Same code
Distributed
akka.actor.deployment { /path/to/actor { remote { nodes = ["somewhere:2552"] } }}
configure an actor as remote
Remote actor
akka.actor.deployment { /path/to/actor { router = "round-robin" nr-of-instances = 5 remote { nodes = ["wallace:2552", "gromit:2552", ...] } }}
several instances, round robin routing
Routers
Cluster
Decentralised peer-to-peer
Automatic failover and adaptive rebalancing
Gossip protocol
inspired by
Amazon’s Dynamo
Basho’s Riak
Add-ons
IntegrationCamel, Spring, ZeroMQ, AMQP
HTTPPlay framework, REST APIs
Durable mailboxesFile system, Redis, MongoDB, Zookeeper
MicrokernelStand-alone deployment
TestKitTesting toolkit for Akka actors
ConsoleTrace, monitor, manage, provision
Simpler to build systems that are
highly concurrent
truly scalable
fault tolerant
Learn more
http://akka.io
http://typesafe.com
Thank you!
?