async - react, don't wait - pingconf

Post on 15-Jan-2015

1.391 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Slides from my talk about Async with Play framework Scala and Java from the PingConf in Budapest january 2014

TRANSCRIPT

AsyncReact instead of waiting for better times

Johan Andrén johan.andren@mejsla.se @apnylle

Who am I?Java/JVM - Last 8 yearsScala & Play - Last 2 years

@apnylleJohan Andrén

ConsultantHome

You are here now

Most modern web frameworks

Request

Response

t1

t1

Thread pool

What does that thread spend most of its time doing?

Hint:

Wait

resource

Request

Response

Blocked

your logic

your logic

Request

Response

Why is this a problem?

20 db connections 200 threads

200 concurrent db-using reqs

1 req for non db url

Why is this a problem? (also)

• Cloud providers - thread cap/node

• Streaming data over http

• many threads - overhead(s)

How would we like it to work?

No logic executing: no thread taken

resource

We´ll call you

Our logic

Our logic ResourceAsync API

Don´t call us

QWe can’t really do more cpu-bound work than the number of cores simultaneously

So If no thread ever blocks

we don’t really need:

more threads than cores

What do we need?

• Ways to do callbacks

• Framework support

but doesn’t callbacks lead to...

1 GMaps.geocode({! 2 address: fromAddress,! 3 callback: function( results, status ) {! 4 if ( status == "OK" ) {! 5 fromLatLng = results[0].geometry.location;! 6 GMaps.geocode({! 7 address: toAddress,! 8 callback: function( results, status ) {! 9 if ( status == "OK" ) {!10 toLatLng = results[0].geometry.location;!11 map.getRoutes({!12 origin: [ fromLatLng.lat(), fromLatLng.lng() ],!13 destination: [ toLatLng.lat(), toLatLng.lng() ],!14 travelMode: "driving",!15 unitSystem: "imperial",!16 callback: function( e ){!17 console.log("ANNNND FINALLY here's the directions..." );!18 // do something with e!19 }!20 });!21 }!22 }!23 });!24 }!25 }!26 });!

”Callback Hell”?

Not with better abstractions!

25 }!26 });

• Futures / Promises

• Actors

• Iteratees

IntermissionSHARK!

SHARK! SHARK!

Futures”I promise that I will give you a Kitten, when you are old enough to take care of

it””When I (in the future) Get a kitten I will play with it

all day”

Promise[Kitten]complete(kitten)failure(Reason)

onComplete(play) onFailure(cry)

Side effect!!!Future[Kitten]

Transforming the future

Future[A] Future[B]

map(f: A => B)a b

f(a)

If the future isn’t that bright

Future[A] Future[B]

Map

Example - the play web client

: Future[SimpleResult]

Example - the play web client

Chaining futures

map(A => B)

Future[B]

map(B => C)

Future[C]

Future[A]WS Response => model Object

model Object => HTML

Even more flexibility

Future[A] Future[B]

flatMap(A => Future[B])

List[Future[A]]

Future.sequenceFuture[List[A]]

Even more even more flexibility

List[Future[A]]

Future.firstCompletedOfFuture[A]

List[Future[A]]Future.fold

Future[B]

But, wait a minute, where is it executed?

• Scala

• Implicit execution context required

• map(A => B)(implicit ctx)

• Java • Default

• map(A => B, CTX)

ExecutionContext

Runnable:s

ThreadpoolT1 T2 Tn

So, when should I use futures?

• When talking to other services (ws, db, etc)

• For parallell work

• Simple one off background stuff

• ?

Actors

Inbox

Behaviour

State

Example - actors and the ask pattern

Example - actors and the ask pattern

Example - actors and the ask pattern

Request 1

Request 2

Request 3

Response 1

Response 2

Response 3

Thread 1

Thread 2

Thread 3

Shared Mutable

Resource

Threads blocked!

Request 1

Request 2

Request 3

Response 1

Response 2

Response 3

Actor with

state

So, when should I use actors?

• When you need state

• Streaming data into or out of play

• As a base for event driven apps

• Background work

• ?

IterateesSmall, simple and witty illustration of Iteratees

(best case: including cats)

Traditional imperative Java IO

Thread blocked!

How would we want it to work?

• react on each chunk

• build something out of those chunks

• bail out early

Let’s model that:

Input

El(element) EOF Empty

Let’s model that:

Step

Cont(Input =>Step) Done(result) Error(why)

What to do with next input

Iteratee

Enumerator

Let’s model that:

Cont(Input =>Step)EL(”kittenA”)

EL(”kittenB”)

EOF

Cont(Input =>Step)

Cont(Input =>Step)

Done(List(”kittenA”,”kittenB”))

(Starting state)

Let’s model that:

Enumerator[E] Iteratee[E, R]

E: The type of the chunks

Even moar:

Enumerator[A] Iteratee[B, R]

Enumeratee[A, B]

Example

Example

Example

So, when should I use Iteratees?

• When you need to stream data

• You probably already do! (BodyParsers)

• ?

Async: What to look out for

• IO • Enumerator.from{File|Stream}

• Really heavy/long computations

• Blocking by mistake

• JDBC

How to make sync async• Futures

• Important: using a separate bounded ExecutionContext

• scala.concurrent.blocking

• Actors

Async: Drawbacks

• MMMM - (Monad-Mixing Makes Mess)

• Shorter stacks - stacktraces not that helpful :(

• ThreadLocal

Is there a case where async shouldn’t be used?

Possibly: Few (and predictable) concurrent connections and a need of as

good response times as possible

Entirely cpu bound apps

Final words

Play makes async easy (and fun)both with Java and Scala!

Also: Know your abstractions!

Johan Andrén johan.andren@mejsla.se @apnylle

K Thx Bye!

Qs?

github.com/johanandren/ping-conf-scala github.com/johanandren/ping-conf-java

top related