async - react, don't wait - pingconf

51
Async React instead of waiting for better times Johan Andrén johan.andren@mejsla.se @apnylle

Upload: johan-andren

Post on 15-Jan-2015

1.408 views

Category:

Technology


1 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Async - react, don't wait - PingConf

AsyncReact instead of waiting for better times

Johan Andrén [email protected] @apnylle

Page 2: Async - react, don't wait - PingConf

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

@apnylleJohan Andrén

ConsultantHome

You are here now

Page 3: Async - react, don't wait - PingConf

Most modern web frameworks

Request

Response

t1

t1

Thread pool

Page 4: Async - react, don't wait - PingConf

What does that thread spend most of its time doing?

Hint:

Page 5: Async - react, don't wait - PingConf

Wait

resource

Request

Response

Blocked

your logic

your logic

Request

Response

Page 6: Async - react, don't wait - PingConf

Why is this a problem?

20 db connections 200 threads

200 concurrent db-using reqs

1 req for non db url

Page 7: Async - react, don't wait - PingConf

Why is this a problem? (also)

• Cloud providers - thread cap/node

• Streaming data over http

• many threads - overhead(s)

Page 8: Async - react, don't wait - PingConf

How would we like it to work?

No logic executing: no thread taken

resource

Page 9: Async - react, don't wait - PingConf

We´ll call you

Our logic

Our logic ResourceAsync API

Don´t call us

Page 10: Async - react, don't wait - PingConf

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

Page 11: Async - react, don't wait - PingConf

What do we need?

• Ways to do callbacks

• Framework support

but doesn’t callbacks lead to...

Page 12: Async - react, don't wait - PingConf

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”?

Page 13: Async - react, don't wait - PingConf

Not with better abstractions!

25 }!26 });

• Futures / Promises

• Actors

• Iteratees

Page 14: Async - react, don't wait - PingConf

IntermissionSHARK!

SHARK! SHARK!

Page 15: Async - react, don't wait - PingConf

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”

Page 16: Async - react, don't wait - PingConf

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

onComplete(play) onFailure(cry)

Side effect!!!Future[Kitten]

Page 17: Async - react, don't wait - PingConf

Transforming the future

Future[A] Future[B]

map(f: A => B)a b

f(a)

Page 18: Async - react, don't wait - PingConf

If the future isn’t that bright

Future[A] Future[B]

Map

Page 19: Async - react, don't wait - PingConf

Example - the play web client

: Future[SimpleResult]

Page 20: Async - react, don't wait - PingConf

Example - the play web client

Page 21: Async - react, don't wait - PingConf

Chaining futures

map(A => B)

Future[B]

map(B => C)

Future[C]

Future[A]WS Response => model Object

model Object => HTML

Page 22: Async - react, don't wait - PingConf

Even more flexibility

Future[A] Future[B]

flatMap(A => Future[B])

List[Future[A]]

Future.sequenceFuture[List[A]]

Page 23: Async - react, don't wait - PingConf

Even more even more flexibility

List[Future[A]]

Future.firstCompletedOfFuture[A]

List[Future[A]]Future.fold

Future[B]

Page 24: Async - react, don't wait - PingConf

But, wait a minute, where is it executed?

• Scala

• Implicit execution context required

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

• Java • Default

• map(A => B, CTX)

Page 25: Async - react, don't wait - PingConf

ExecutionContext

Runnable:s

ThreadpoolT1 T2 Tn

Page 26: Async - react, don't wait - PingConf

So, when should I use futures?

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

• For parallell work

• Simple one off background stuff

• ?

Page 27: Async - react, don't wait - PingConf

Actors

Inbox

Behaviour

State

Page 28: Async - react, don't wait - PingConf

Example - actors and the ask pattern

Page 29: Async - react, don't wait - PingConf

Example - actors and the ask pattern

Page 30: Async - react, don't wait - PingConf

Example - actors and the ask pattern

Page 31: Async - react, don't wait - PingConf

Request 1

Request 2

Request 3

Response 1

Response 2

Response 3

Thread 1

Thread 2

Thread 3

Shared Mutable

Resource

Threads blocked!

Page 32: Async - react, don't wait - PingConf

Request 1

Request 2

Request 3

Response 1

Response 2

Response 3

Actor with

state

Page 33: Async - react, don't wait - PingConf

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

• ?

Page 34: Async - react, don't wait - PingConf

IterateesSmall, simple and witty illustration of Iteratees

(best case: including cats)

Page 35: Async - react, don't wait - PingConf

Traditional imperative Java IO

Thread blocked!

Page 36: Async - react, don't wait - PingConf

How would we want it to work?

• react on each chunk

• build something out of those chunks

• bail out early

Page 37: Async - react, don't wait - PingConf

Let’s model that:

Input

El(element) EOF Empty

Page 38: Async - react, don't wait - PingConf

Let’s model that:

Step

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

What to do with next input

Page 39: Async - react, don't wait - PingConf

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)

Page 40: Async - react, don't wait - PingConf

Let’s model that:

Enumerator[E] Iteratee[E, R]

E: The type of the chunks

Page 41: Async - react, don't wait - PingConf

Even moar:

Enumerator[A] Iteratee[B, R]

Enumeratee[A, B]

Page 42: Async - react, don't wait - PingConf

Example

Page 43: Async - react, don't wait - PingConf

Example

Page 44: Async - react, don't wait - PingConf

Example

Page 45: Async - react, don't wait - PingConf

So, when should I use Iteratees?

• When you need to stream data

• You probably already do! (BodyParsers)

• ?

Page 46: Async - react, don't wait - PingConf

Async: What to look out for

• IO • Enumerator.from{File|Stream}

• Really heavy/long computations

• Blocking by mistake

• JDBC

Page 47: Async - react, don't wait - PingConf

How to make sync async• Futures

• Important: using a separate bounded ExecutionContext

• scala.concurrent.blocking

• Actors

Page 48: Async - react, don't wait - PingConf

Async: Drawbacks

• MMMM - (Monad-Mixing Makes Mess)

• Shorter stacks - stacktraces not that helpful :(

• ThreadLocal

Page 49: Async - react, don't wait - PingConf

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

Page 50: Async - react, don't wait - PingConf

Final words

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

Also: Know your abstractions!

Page 51: Async - react, don't wait - PingConf

Johan Andrén [email protected] @apnylle

K Thx Bye!

Qs?

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