Actors & Akka
Purposes?
Damien Katz(CTO in CouchBase):
-
Beginner: "Threads are hard."
-
Intermediate: "Don't fear multithreading."
-
Expert: "Threads are hard."
Agenda
-
Inroduction
-
Concurrency problems
- Reactive programming
-
Actor Model
-
Akka + Some Code
-
Conclusions
Moore's LAw
MOORE'S LAW
-
Coined in the 1965 paper by Gordon E. Moore
-
The number of transistors is doubling every 18 months
-
Processors manufacturing solves our problems for years
but it is dead
-
Chips got big enough, signal is no longer takes cycle time
- Problems with heat dissipation
World becomes parallel and concurrent
Reactive Programming
In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow.
REACTIVE PROGRAMMING
Parallelism VS COncurrency
Concurrency IS NOT Parallelism
Concurrency is the ability to run in parallel
Parallelism is really in parallel execution
CONCURRENCY Problem
The main problem of concurrency model is
MUTABLE STATE
Lets to be more accurate. Problem is
MUTABLE SHARED STATE
And then add some LOCKING mechanism there.
What is a Value?
The VALUE is something that doesn't change
42, "Name", "07/22/2014", etc.
WHAT IS An Identity?
A stable logical entity
associated with a series of different
VALUES over time
What is a state?
Specific IDENTITY has a particular point in time with associated set of VALUES.
If IDENTITY has different VALUES in different timeframes then this IDENTITY has a STATE.
Any Problems?
IDENTITY & VALUE should be separate from each other in scope of state.
Known Solutions
So we need to new level of abstraction
- Shared State Concurrency (Common sync techniques)
-
Software Transactional Memory (Managed References)
-
Message-Passing Concurrency (Actors Model)
-
Dataflow Concurrency (Dataflow-based processes)
Actors MODEL - History
-
Was found in 1973 by Carl Hewitt
-
First was a theory for concurrency computing
-
Then became a theory ground for Actor implementations
-
Has native implementation in Erlang, Clojure, Scala
-
Has a lot of libraries in other languages
Actors model - Key Principals
-
Actors instead of Objects: Everything is Actor
-
No shared state between Actors
- Asynchronous immutable message-passing
- Mailboxes as queue to buffer incoming messages
- Actor has addresses
-
send messages to other actors
-
create new actors
-
set the logic for next incoming message
Actors Model - Schema
Akka Library
-
Author: Jonas Boner (Terracotta JVM Clusterring, JRockit JVM)
-
Apache V2 License
-
Implementations: Scala, Java
-
JVM Concurrency model: Fork-Join
Akka - Key features
-
300 bytes per actor
-
Supervisor strategy
-
Set of Actors per set of Threads
-
"Let it crash" behaviour in exceptional situations
- Distributed cluster environment support
Time for code
public class Worker extends UntypedActor {
@Override
public void onReceive(Object message) {
if (message instanceof Work) {
BigInteger bigInt = new CalculateFactorial().calculate();
getSender().tell(new Result(bigInt), getSelf());
} else
unhandled(message);
}
public static Props createWorker() {
return Props.create(Worker.class, new ArraySeq<Object>(0));
}
}
time for code
public class Master extends UntypedActor {
private long messages = 1000000;
private ActorRef workerRouter;
private ArrayList list = new ArrayList();
public Master() {
workerRouter = this.getContext().actorOf(Worker.createWorker().withRouter(new RoundRobinRouter(8)), "workerRouter");
}
@Override
public void onReceive(Object message) {
if (message instanceof Calculate) {
processMessages();
} else if (message instanceof Result) {
list.add(((Result) message).getFactorial());
if (list.size() == messages) end();
} else unhandled(message);
}
private void processMessages() {
for (int i = 0; i < messages; i++) workerRouter.tell(new Work(), getSelf());
}
private void end() {getContext().system().shutdown();}
}
Time for code
public class Main {
public static void main(String[] args) {
new Main().run();
}
private void run() {
ActorSystem system = ActorSystem.create("FactorialSystem");
ActorRef master = system.actorOf(Master.createMaster(), "master");
master.tell(new Calculate(), ActorRef.noSender());
}
}
Do you wanna See some Scala?
case class Work()
case class Result(factorial: Int)
class Worker extends Actor with ActorLogging {
def receive = {
case Work => sender ! Result(new CalculateFactorial().calculate())
}
}
//-----------
val system = ActorSystem("factorial")
val master = system.actorOf(Props[Master], name = "master")
master ! Work
Actors - Real World usage
-
Yandex.Автомобили
-
Yandex.Недвижимость
-
Facebook chat application
-
RabbitMQ
-
Apache CoucheDB
-
Jabber.org
Conclusions
Pros:
-
Higher abstraction layer
-
Avoid all concurrency problems such as: Race conditions, Deadlocks, Starvations, Live locks
-
Clustering
Cons:
-
Not suitable if we realy have to get shared state
-
Not suitable if we need to have synchronous approach
-
It is not trivial to divide task onto smaller tasks
USEFUL LINKS & RESOURCES
Reactive Programming:
Actor's theory:
Akka:
actors-akka
By Yegor Bondar
actors-akka
Akka framework overview
- 1,275