Reactive applications using Akka

98
[email protected] - Liferay Inc and MadridJUG @miguelinlas3 Miguel Ángel Pastor Olivar Reactive Applications Building concurrent and distributed apps using Akka Saturday, October 19, 13

description

Basic intro to reactive applications concepts and a crash course on some of the tools Akka and some other providers give use

Transcript of Reactive applications using Akka

Page 1: Reactive applications using Akka

[email protected] - Liferay Inc and MadridJUG

@miguelinlas3

Miguel Ángel Pastor Olivar

Reactive ApplicationsBuilding concurrent and distributed apps using Akka

Saturday, October 19, 13

Page 2: Reactive applications using Akka

Writing software for the Liferay platform team

About me

Phd student? on distributed and cloud systems

Scala enthusiast

Twitter: @miguelinlas3

Saturday, October 19, 13

Page 3: Reactive applications using Akka

Reactive apps: do we really need them?

Crash course on basic Akka concepts

Old known problems

A quick look into newer (and more fun tools)

Agenda

Saturday, October 19, 13

Page 4: Reactive applications using Akka

Applications has become extremely demanding

New kind of systems

Event driven, scalable , resilient, responsive

This is what Reactive Applications are all about

Reactive applications

Saturday, October 19, 13

Page 5: Reactive applications using Akka

BlockingCaller blocked. Wait for the results

Non blockingCaller not blocked. Need to pool

AsynchronousCaller not blocked. Select, epoll, signals

Event drivenMessage flowing through the system

Reactive applications: definitions

Saturday, October 19, 13

Page 6: Reactive applications using Akka

Basic pillars

Saturday, October 19, 13

Page 7: Reactive applications using Akka

Basic pillars

Event Driven

Saturday, October 19, 13

Page 8: Reactive applications using Akka

Basic pillars

Event Driven

Resilient

Saturday, October 19, 13

Page 9: Reactive applications using Akka

Basic pillars

Event Driven

Resilient Scalable

Saturday, October 19, 13

Page 10: Reactive applications using Akka

Basic pillars

Event Driven

Responsive

Resilient Scalable

Saturday, October 19, 13

Page 11: Reactive applications using Akka

Going event driven

Old known problems,The actor model

Saturday, October 19, 13

Page 12: Reactive applications using Akka

Going Event Driven

Saturday, October 19, 13

Page 13: Reactive applications using Akka

Going Event Driven

Shared Memory

Saturday, October 19, 13

Page 14: Reactive applications using Akka

Going Event Driven

Shared Memory

Saturday, October 19, 13

Page 15: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1

Saturday, October 19, 13

Page 16: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

Saturday, October 19, 13

Page 17: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

Saturday, October 19, 13

Page 18: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

Saturday, October 19, 13

Page 19: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

R/W

Saturday, October 19, 13

Page 20: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

R/WR/W

Saturday, October 19, 13

Page 21: Reactive applications using Akka

Going Event Driven

Shared Memory

Thread 1 Thread 2

R/WR/W AVOID IT!!

Saturday, October 19, 13

Page 22: Reactive applications using Akka

Going event driven: problems with locks

Saturday, October 19, 13

Page 23: Reactive applications using Akka

Going event driven: problems with locks

Composition

Saturday, October 19, 13

Page 24: Reactive applications using Akka

Going event driven: problems with locks

CompositionLocks don´t compose

Saturday, October 19, 13

Page 25: Reactive applications using Akka

Going event driven: problems with locks

Composition GranularityLocks don´t compose

Saturday, October 19, 13

Page 26: Reactive applications using Akka

Going event driven: problems with locks

Composition GranularityLocks don´t compose

Have I taken too few locks? Too many?

Saturday, October 19, 13

Page 27: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

Encapsulation

Locks don´t compose

Have I taken too few locks? Too many?

Saturday, October 19, 13

Page 28: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

Encapsulation

Locks don´t compose

Have I taken too few locks? Too many?

Breaking abstractions

Saturday, October 19, 13

Page 29: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

EncapsulationCorrectness

Locks don´t compose

Have I taken too few locks? Too many?

Breaking abstractions

Saturday, October 19, 13

Page 30: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

EncapsulationCorrectness

Locks don´t compose

Have I taken too few locks? Too many?

Have I taken the correct lock?

Breaking abstractions

Saturday, October 19, 13

Page 31: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

EncapsulationCorrectness

Ordering

Locks don´t compose

Have I taken too few locks? Too many?

Have I taken the correct lock?

Breaking abstractions

Saturday, October 19, 13

Page 32: Reactive applications using Akka

Going event driven: problems with locks

Composition Granularity

EncapsulationCorrectness

Ordering

Locks don´t compose

Have I taken too few locks? Too many?

Have I taken the correct lock?

Have I used the correct order?

Breaking abstractions

Saturday, October 19, 13

Page 33: Reactive applications using Akka

Asynchronous message/event passing

Workflow of the events through your system

Benefits:Better throughputLower latenciesLoosely coupled solutions

Going event driven: designing your system

Saturday, October 19, 13

Page 34: Reactive applications using Akka

Going event driven: Amdahl’s law

Saturday, October 19, 13

Page 35: Reactive applications using Akka

Going event driven: the actor model

Fundamental unit of computation that embodies:• Processing• Storage• Communication

Three axioms. When an Actor receives a message it can:• Create new Actors• Send messages to Actors it knows• Designate how it should handle the next message it receives

Carl Hewitt

Saturday, October 19, 13

Page 36: Reactive applications using Akka

Going event driven: the actor model

Saturday, October 19, 13

Page 37: Reactive applications using Akka

Going event driven: the actor model

Saturday, October 19, 13

Page 38: Reactive applications using Akka

Going event driven: the actor model

Saturday, October 19, 13

Page 39: Reactive applications using Akka

Going event driven: the actor model

Zero sharing

Isolated, lightweight event based processes

Communication through asynchronous message passing

Location transparent

Built-in supervision

Saturday, October 19, 13

Page 40: Reactive applications using Akka

Actor model: Define a new actor

public class MetricsProcessorActor extends UntypedActor {

public void onReceive(Object message) { if (message instanceof JVMMetric) { JVMMetric jvmMetric = (JVMMetric)message;

_dataStore.save(jvmMetric); } }

private DataStore _dataStore = new LogDataStore();}

Saturday, October 19, 13

Page 41: Reactive applications using Akka

Actor model: Creating an actor

ActorSystem _agentSystem = ActorSystem.create("AgentSystem");

ActorRef metricsActor = _agentSystem.actorOf(

new Props(new UntypedActorFactory() { @Override public Actor create() {

return new MetricsActor(metricsActor);}

}),"metricsActor");

Saturday, October 19, 13

Page 42: Reactive applications using Akka

Actor model: Getting a reference

ActorSystem _agentSystem = ActorSystem.create("AgentSystem");

ActorRef handshakeActor = _agentSystem.actorFor(

"akka://MonitoringServiceSystem@localhost:5557/user/handshakeActor");

Saturday, October 19, 13

Page 43: Reactive applications using Akka

Actor model: Sending a message

metricsActor.tell(new JVMMessage("JVM-MemoryUsage", new Date().getTime()));

Saturday, October 19, 13

Page 44: Reactive applications using Akka

Actor model: Replying to a message

public class HandshakeActor extends UntypedActor {

public void onReceive(Object message) {

if (message instanceof AuthMessage) { AuthMessage authMessage = (AuthMessage)message;

if (authMessage.getUser() == "migue" && authMessage.getCredentials() == "migue")

getSender().tell("ok"); else

getSender().tell("fail"); } else throw new IllegalStateException("Unable to handle " +

message); }}

Saturday, October 19, 13

Page 45: Reactive applications using Akka

Actor model: Switching implementation

public class MetricsProcessorActor extends UntypedActor {

public void onReceive(Object message) { if (message instanceof SwappingMessage) { getContext().become(altPersistence, false) }

} Procedure<Object> altPersistence = new Procedure<Object>() { @Override public void apply(Object message) { altDatastore.save(message); }

DataStore altDatastore = new AltDataStore();};

private DataStore _dataStore = new LogDataStore();}

Saturday, October 19, 13

Page 46: Reactive applications using Akka

Actor model: Routing

final ActorSystem monitoringServiceSystem =ActorSystem.create("MonitoringServiceSystem");

ActorRef metricsActor = monitoringServiceSystem.actorOf(

new Props(MetricsProcessorActor.class).withRouter( new RoundRobinRouter(100), "metricsActor"); }

metricsActor.tell(new JVMMessage("JVM-MemoryUsage", new Date().getTime()));

Dealing with routers does not change our code

Saturday, October 19, 13

Page 47: Reactive applications using Akka

Actor model: Configuring a router

akka { actor { deployment { /metricsActor { router = round-robin nr-of-instances = 100 } } }}

Saturday, October 19, 13

Page 48: Reactive applications using Akka

Going scalable

Distributed computing,The actor model

Saturday, October 19, 13

Page 49: Reactive applications using Akka

Going scalable: scalability

I really do have an scalability problem ...

if my system is fast for a single user but slow when the system is under heavy load

Saturday, October 19, 13

Page 50: Reactive applications using Akka

Going scalable: transparent distributed computing

Distributed shared mutable state

Distributed objects

Distributed transactions

Saturday, October 19, 13

Page 51: Reactive applications using Akka

Going scalable: transparent distributed computing

Synchronous method dispatching across the network is a bad idea

Ignores partial failures

Raises Latency

General scalability and DC concerns

Saturday, October 19, 13

Page 52: Reactive applications using Akka

Going scalable: transparent distributed computing

EMBRACE THE NETWORK!!

Saturday, October 19, 13

Page 53: Reactive applications using Akka

Going scalable: remote actors

akka { actor { deployment { /metricsActor {

remote = "akka://monitorSystem@name:5557"

} } }}

final ActorSystem monitoringServiceSystem =ActorSystem.create("MonitoringServiceSystem");

ActorRef metricsActor = monitoringServiceSystem.actorOf( new Props(MetricsProcessorActor.class), "metricsActor");

No changes are required in our existing code!!

Saturday, October 19, 13

Page 54: Reactive applications using Akka

Going resilient

Error handling

Saturday, October 19, 13

Page 55: Reactive applications using Akka

Going resilient: common problems

Single thread of control

Thread blows up --> you are screwed

Error handling within single thread

Errors don´t get propagated

Defensive programmingTangled within business logicScattered along all our codebase

Saturday, October 19, 13

Page 56: Reactive applications using Akka

Going resilient: actor topology and supervision

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B5

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 57: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B5

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 58: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 59: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 60: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 61: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7

Saturday, October 19, 13

Page 62: Reactive applications using Akka

Supervision strategies: One for one

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

Saturday, October 19, 13

Page 63: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B5

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 64: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 65: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 66: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 67: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 68: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B6

B7

Saturday, October 19, 13

Page 69: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 70: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B6

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 71: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 72: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B7

Saturday, October 19, 13

Page 73: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 74: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

B7

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 75: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 76: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

Saturday, October 19, 13

Page 77: Reactive applications using Akka

Supervision strategies: One for all

System

A1

A2

A4

B1

B2

B4

B3

A3

/A1

/A1/A2

/A1/A2/A4

/A1/A3

/B1

/B1/B2

/B1/B2/B4

/B1/B3

/B1/B3/B5

/B1/B2/B6

/B1/B2/B7B5

B6

B7

Saturday, October 19, 13

Page 78: Reactive applications using Akka

Going resilient: configure supervision

final SupervisorStrategy supervisorStrategy = new OneForOneStrategy(

3, Duration.create(1, TimeUnit.MINUTES),new Class<?>[] {Exception.class});

_metricsActor = _cloudServiceSystem.actorOf( new Props(MetricsProcessorActor.class).

withRouter( new RoundRobinRouter(100).

withSupervisorStrategy( supervisorStrategy)),

"metricsActor");

Supervision strategies are pluggable and you can develop and configure your own

Saturday, October 19, 13

Page 79: Reactive applications using Akka

More tools

We deserve better and more fun tools

Saturday, October 19, 13

Page 80: Reactive applications using Akka

More tools: futures

•Spawn concurrent computations

•Write once - Read many

•Freely sharable

•Non-blocking composition

•Composable (monadic operations)

•Managing failure

Saturday, October 19, 13

Page 81: Reactive applications using Akka

More tools: futures

val f: Future[List[String]] = future { session.getRecentPosts}

// handle both cases: Success and Failuref onComplete { case Success(posts) => for (post <- posts) println(post) case Failure(t) => println("An error has occured: " +

t.getMessage)}

// only handle Successf onSuccess { case posts => for (post <- posts) println(post)}

// only handle Failuref onFailure { case t => println("An error has occured: " + t.getMessage)}

Saturday, October 19, 13

Page 82: Reactive applications using Akka

More tools: agents

•Reactive memory cells

•Send update function to an agent

•Reads are “free”

•Composable

•Originally in Clojure, borrowed by Akka

Saturday, October 19, 13

Page 83: Reactive applications using Akka

More tools: agents

// declare the agentval counter = Agent(0)

// send the function: enqueued the changecounter send { _ + 1}

// long running or blocking operations

implicit val ec = defineSomeExecutionContext()agent sendOff blockingOperation

// read the agent’ s valueval agentValue = counter.value

Saturday, October 19, 13

Page 84: Reactive applications using Akka

More tools: software transactional memory

Sometimes we will deal with shared stateHeap + Stack: transactional dataset:

Begin, commit, rollback

Retry on collision

Rollback on abort

Transaction composability

Saturday, October 19, 13

Page 85: Reactive applications using Akka

More tools: reactive extensions

•Futures + Stream concept

•Composables

•Async and event based

•Push collections

•JVM available through the RxJava project

Saturday, October 19, 13

Page 86: Reactive applications using Akka

More tools: reactive extensions

def simpleComposition() { customObservableNonBlocking() .skip(10) .take(5) .map({ stringValue -> return stringValue + "_transformed"}) .subscribe({ println "nextElement => " + it})} // we should an output like this

nextElement => foo_10_transformednextElement => foo_11_transformednextElement => foo_12_transformednextElement => foo_13_transformednextElement => foo_14_transformed

Saturday, October 19, 13

Page 87: Reactive applications using Akka

More tools: reactive extensions

def Observable<T> getData(int id) { if(availableInMemory) { return Observable.create({ observer -> observer.onNext(valueFromMemory); observer.onCompleted(); }) } else { return Observable.create({ observer -> executor.submit({ try { T value = getValueFromRemoteService(id); observer.onNext(value); observer.onCompleted(); }catch(Exception e) { observer.onError(e); } }) }); }}

Saturday, October 19, 13

Page 88: Reactive applications using Akka

Useful approaches

Where should I use each tool?

Saturday, October 19, 13

Page 89: Reactive applications using Akka

Layers of complexity

Declarative & immutable coreLogic or functional programmingFutures and/or dataflow

Non-determinism when neededActors, Agents or Rx

Shared mutabilityProtected by Software Transactional Memory

Finally, only if it is really neededLocks and explicit threads

Saturday, October 19, 13

Page 90: Reactive applications using Akka

Takeways

A quick summary

Saturday, October 19, 13

Page 91: Reactive applications using Akka

Takeaways

Go reactive

Avoid locking (share nothing, lock free algs)

Already in the JVM? Akka could be good choice

Distributed systems are hard

Use the correct level of abstraction

And remember ...

Saturday, October 19, 13

Page 92: Reactive applications using Akka

Takeaways

When all you have is a hammer everything looks like

a nail.

Choose the

right tool for your job!

Saturday, October 19, 13

Page 93: Reactive applications using Akka

Questions?

And let’s hope answers

Saturday, October 19, 13

Page 94: Reactive applications using Akka

References

Interesting resources

Saturday, October 19, 13

Page 98: Reactive applications using Akka

References: frameworks and toolkits

Cloud Haskell

NodeJS

Netty IO

Finagle

Saturday, October 19, 13