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

Async - react, don't wait - PingConf

Jan 15, 2015

Download

Technology

Johan Andrén

Slides from my talk about Async with Play framework Scala and Java from the PingConf in Budapest january 2014
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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