Async - react, don't wait - PingConf

Post on 15-Jan-2015

1.391 views 1 download

Tags:

description

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

Transcript of Async - react, don't wait - PingConf

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