61
8/9/2019 Fast Track to Akka http://slidepdf.com/reader/full/fast-track-to-akka 1/61 1 Fast Track to Akka – Part 1 Philipp Haller Typesafe Inc. July 11-12, 2012

Fast Track to Akka

Embed Size (px)

Citation preview

Page 1: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 1/61

1

Fast Track to Akka – Part 1

Philipp Haller

Typesafe Inc.

July 11-12, 2012

Page 2: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 2/61

2

Agenda

Why Akka?

Actors

Futures

Testing Actor Systems

Page 3: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 3/61

Page 4: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 4/614

The problem

It is way too hard to build correct highly-concurrent systems truly scalable systems fault-tolerant systems

... using today’s tools

Page 5: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 5/615

Vision: Simpler Concurrency and Distribution

... with a single, unified Programming model Runtime Open-source distribution

Page 6: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 6/61

Manage system overload

Page 7: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 7/617

Scale up & out

Page 8: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 8/61

Replicate and distribute

for Fault-Tolerance

Page 9: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 9/619

Architecture

Page 10: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 10/6110

Architecture

Page 11: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 11/61

11

Architecture

Page 12: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 12/61

12

Where is Akka used?

FINANCE

 Stock trend Analysis &Simulation

  Event-drivenmessaging systems

BETTING & GAMING

  Massive multiplayeronline gaming

 High throughput andtransactional betting

TELECOM

  Streaming medianetwork gateways

SIMULATION

  3D simulationengines

E-COMMERCE

 Social mediacommunity sites

Page 13: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 13/61

Page 14: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 14/61

14

What is an Actor?

Page 15: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 15/61

Page 16: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 16/61

16

What is an Actor?

Page 17: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 17/61

A M d l f C

Page 18: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 18/61

18

Actor Model of Concurrency

  Implements Message-Passing Concurrency

  Share NOTHING

  Isolated  lightweight processes  Communicates through messages

  Asynchronous and  non-blocking

 Each actor has a mailbox (message queue)

A M d l B fi

Page 19: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 19/61

19

Actor Model Benefits

 Easier to reason about

 Raised abstraction level  Easier to avoid

Race conditions Deadlocks Starvation Live locks

  Location Transparency, configuration-driven (adaptive)

deployment

B i A t

Page 20: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 20/61

20

Basic Actor

1   case object   Tick

2

3   class   Counter   extends   Actor {

4   var   counter = 0   //STATE

5

6   def   receive = {   //BEHAVIOR

7   case   Tick   =>

8   counter += 1

9   println(counter)

10

  }11   }

A t S t

Page 21: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 21/61

21

Actor Systems

 Every actor is created within the context of an actor system

 The actor system is the unit for managing shared facilities like

scheduling services, configuration, logging, etc.  Several actor systems with different configurations may

co-exist within the same JVM instance (there is no globalstate within Akka itself)

 There may be millions of actors within a single actor system

Creating Actors

Page 22: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 22/61

22

Creating Actors

 Create an actor system:

1   val   system = ActorSystem()

 Create an actor:

1   val   counter = system.actorOf(Props[Counter],

"my-counter")

  counter   is an  ActorRef

You can’t instantiate an Actor directly

Page 23: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 23/61

23

You can t instantiate an Actor directly

 This will throw an  Exception:

1   scala>   new   Counter

2   akka.actor.ActorInitializationException:

3   You cannot create an instance of [Counter] explicitly

using the constructor (new).

4   You have to use one of the factory methods to create

a   new   actor. Either use:

5   ’val actor = context.actorOf(Props[MyActor])’   (to

create a supervised child actor from within an

actor), or

6   ’val actor = system.actorOf(Props[MyActor])’   (tocreate a top level actor from the ActorSystem), or

7   ...

Send: !

Page 24: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 24/61

24

Send: !

 Pronounced ”bang”, ”tell” or ”fire and forget”

1   counter   !   Tick

 Asynchronous, does  not  block

Two and a half ways to stop Actors

Page 25: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 25/61

25

Two-and-a-half ways to stop Actors

  Stop:

1   system.stop(counter)

will stop the actor after it has finished processing its current message

 Send a Poison Pill:

1   counter   !   PoisonPill

will stop the actor after it has finished processing all previously enqueued

messages

 Send a Kill message:1   counter   !   Kill

will make the actor fail, where the default supervisor action is to stop it

Exercise: A Simple Compute Actor

Page 26: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 26/61

26

Exercise: A Simple Compute Actor

 Create a class ComputeActor that extends Actor   Implement the receive method which should print:

A message with the length of a string when you receive aString

A message with the square of an integer when you receive an

Int  Create an object Main that extends App

 Create an actor system

 Create a ComputeActor

 Send different types of messages (strings, ints, etc.) to theactor

 Shut down the actor system

Replying from an Actor

Page 27: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 27/61

27

Replying from an Actor

 Reply using the sender ActorRef 

1   class   ComputeActor   extends   Actor {

2   def   receive = {

3   case   s: String   =>4   sender   !   s.length

5   ...

6   }

7   }

Page 28: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 28/61

Send: ? and ask

Page 29: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 29/61

29

Send: ? and ask

 Used to receive a reply without involving a mailbox  ”?” pronounced ”ask”  Returns directly with a  Future1, which allows transformation

and forwarding of the reply:

1   import   akka.pattern.{ ask, pipe }

2   import   akka.util.duration._

3

4   val   msgContext = ...   // some addition to reply

5   val   future = computeActor.ask("Hello")(2 seconds)

6   future map {   case   reply: String   =>

7   ComputeResult(msgContext, reply)

8   } pipeTo sender

 Using ”?” and an implicit timeout:

1   implicit val   timeout: Timeout = 2 seconds

2   val   future = computeActor   ?   "Hello"

1more on Futures later

Forwarding

Page 30: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 30/61

30

Forwarding

1   class   Router   extends   Actor {

2   def   nextActor: ActorRef = ...

3

4

  def   receive = {5   case   message   =>

6   nextActor forward message

7   }

8   }

  forward  maintains original sender reference

Exercise: Add replies to ComputeActor

Page 31: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 31/61

31

Exercise: Add replies to ComputeActor

 Reply to the sender with the computation result

 Enable the duration DSL using the following import:

1   import   akka.util.duration._

 Add a test using ”ask” with an explicit timeout

 Add a test using ”?” with an implicit timeout

 Hint: await and obtain the result of a future using

1   Await.result(future, timeout)

 Run using sbt or Eclipse

Agenda

Page 32: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 32/61

32

g

Why Akka?

Actors

Futures

Testing Actor Systems

Future and Promise

Page 33: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 33/61

33

  A Future is a read-handle to a single value (read-many) that

may become available   A Promise is a write-handle to a single value (write-once) that

should be made available

Blocking behaviour

Page 34: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 34/61

g

Two blocking threads

Page 35: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 35/61

g

What we really want

Page 36: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 36/61

Using Futures with Actors

Page 37: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 37/61

37

1   implicit val   timeout: Timeout = 2 seconds

2   // returns a future3   val   future = computeActor   ?   GetAllResults

4

5   // do something asynchronously

6   future map {   case   result: String   =>

7   WrappedResult(result)

8   } pipeTo nextStage

 All operations creating futures need to know where callbacksare to be executed, described by an   ExecutionContext

1   import   context.dispatcher   // when inside an actor2   // OR

3   implicit val   ec = system.dispatcher   // ActorSystem

4   // OR

5   implicit val   ec = ExecutionContext.fromExecutor(...)

Future API: Monadic Operations

Page 38: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 38/61

38

1   def   map[S](f: T   =>   S): Future[S]

2

  def   flatMap[S](f: T   =>   Future[S]): Future[S]3   def   filter(p: T   =>   Boolean): Future[T]

4   def   foreach[U](f: T   =>   U): Unit

Functional Composition

Page 39: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 39/61

39

1   val   rateQuote = Future {

2   connection.getCurrentValue(USD)

3   }

4

  val   purchase = rateQuote map {5   quote   =>

6   if   (isProfitable(quote))

7   connection.buy(amount, quote)

8   else throw new   Exception("not profitable")

9   }

Futures and For-Expressions

Page 40: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 40/61

40

 To enable for-expressions, futures also have  flatMap,  filterand  foreach  combinators

1   val   usdQuote = Future {

connection.getCurrentValue(USD) }

2   val   chfQuote = Future {connection.getCurrentValue(CHF) }

3

4   val   purchase =   for   {

5   usd   <-   usdQuote

6   chf   <-   chfQuote

7   if   isProfitable(usd, chf)

8   }   yield   connection.buy(amount, chf)

Composing when using actors

Page 41: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 41/61

41

  mapTo

1   val   f = (actor   ?   msg).mapTo[String]

  With for-expressions

1   val   r: Future[Int] =   for   {

2   a   <-   (webService   ?   GetResult).mapTo[Int]3   b   <-   (otherWebService   ?   GetResult).mapTo[Int]

4   }   yield   a * b

  . . . and in parallel

1   val   r: Future[Int] =   for   {

2   (a: Int, b: Int)   <-   (actorA   ?   Q) zip (actorB   ?   Q)

3   }   yield   a * b

Page 42: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 42/61

Handling multiple Futures

Page 43: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 43/61

43

1   val   futures = Seq(future1, future2, ...)

2

3   Future.firstCompletedOf(futures)4   Future.reduce(futures)((x, y)   =>   ...)

5   Future.fold(futures)(0)((x, y)   =>   ...)

Transformations: recover

Page 44: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 44/61

44

1   val   purchase: Future[Int] = rateQuote map {

2   quote   =>   connection.buy(amount, quote)

3

  } recover {4   case   quoteExc: QuoteChangedException   =>   0

5   }

 Converts exceptions into results

Transformations: sequence

Page 45: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 45/61

45

1   val   stringFutures =   for   (i   <-   1 to 10)

2   yield   Future { i.toString }

3   val   futureStrings: Future[Seq[String]] =4   Future.sequence(stringFutures)

  Turns a  collection  of Future[X] into a Future[collection[X]]

Transformations: traverse

Page 46: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 46/61

46

1   val   futureListOfPages =

2   Future.traverse(getListOfUrls) { url   =>

3   Future { GET(url) }4   }

 Transforms a  collection[X] to Future[collection[Y]]

Future API

Page 47: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 47/61

47

1   package   akka.dispatch

2

3   trait   Future[+T]   extends   Awaitable[T] {4   ...

5   }

Awaitable[T] and Await

Page 48: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 48/61

48

1   package   akka.dispatch

2

3   object   Await {4   // Blocks the current thread to wait for the given

5   // Awaitable to be ready, returning

6   // the Awaitable’s result

7   def   result[T](awaitable: Awaitable[T],

8   atMost: Duration): T9

10   // Blocks the current thread to wait for the given

11   // Awaitable to be ready

12   def   ready[T <: Awaitable[_]](awaitable: T,

13

  atMost: Duration): T14   }

15

16   // Examples:

17   Await.result(future1, 3 seconds)

18   Await.ready(future2, 2 seconds)

Exercise: Back to the Future

Page 49: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 49/61

49

 From a sequence of N integers produce a sequence of futureswhich are completed after the corresponding time inmilliseconds.

 Compute the list of completed results after 1 second, giventhat at least half of the futures were successful by then.

 By combining the futures one-by-one with

1   val   timeout = Future {

2   Thread.sleep(1000)

3   throw new   Exception("time’s up!")

4   }

construct a combined Future which will contain aSeq[Either[Exception, <result>]]

Page 50: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 50/61

Exercise: More robust cancellation

Page 51: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 51/61

51

 Extend the previous exercise so that the sequence of futurescontains services, mocked by a simple class with adef   dispose(): Unit  method, where the constructor sleeps

for a number of milliseconds.  Ensure that services which are not ready in time are disposed

of when their initialization finishes.

 Ensure that in case of overall failure all services are disposedof.

Agenda

Page 52: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 52/61

52

Why Akka?

Actors

Futures

Testing Actor Systems

Testing in Akka

Page 53: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 53/61

53

 Two ways to test:

Unit testing with  TestActorRef Integration testing with  TestKit  and  TestProbe

Unit Testing

Page 54: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 54/61

54

  TestActorRef: an  ActorRef  which allows testing actors in a   single-threaded  environment behaves like a regular  ActorRef  otherwise

1   import   akka.testkit.TestActorRef

2

3   class   MyActor   extends   Actor {

4   def   receive = {   case   i: Int   =>   println(s(i)) }

5   def   s(a: Any) = a.toString6   }

7

8   val   actorRef = TestActorRef(new   MyActor)(system)

9   val   actor: MyActor = actorRef.underlyingActor

10

11   // check business logic

12   actor.s(1) must beEqualTo("1")

13   // check behavior

14   actor.receive.isDefinedAt("not defined") must

beEqualTo(false)

TestKit with ScalaTest

Page 55: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 55/61

55

1   import   akka.testkit.{ TestKit, ImplicitSender }

2   import   akka.actor.{ ActorSystem, Props }

3   import   org.scalatest.WordSpec

4   import   org.scalatest.junit.JUnitRunner

5

6   @org.junit.runner.RunWith(classOf[JUnitRunner])

7   class   ActorsSpec   extends   TestKit(ActorSystem())   with

8   ImplicitSender   with   WordSpec {9

10   "A ComputeActor"   should {

11   "respond with the length of a string"   in {

12   val   ref = system.actorOf(Props[ComputeActor])

13   ref   !   "Hello world"14   expectMsg(11)

15   }

16   }

17   }

TestKit with Specs2

Page 56: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 56/61

56

1   import   akka.testkit.{ TestKit, ImplicitSender }

2   import   akka.actor.{ ActorSystem, Props }

3   import   org.specs2.mutable.Specification

4   import   org.specs2.time.{ NoTimeConversions   =>   NTC }

5

6   class   ActorsSpec   extends   TestKit(ActorSystem())   with

7   ImplicitSender   with   Specification   with   NTC {

8

9   "A ComputeActor"   should {

10   "respond with the length of a string"   in {

11   val   ref = system.actorOf(Props[ComputeActor])

12   ref   !   "Hello world"

13   expectMsg(11)14   done   // necessary because Specs2 wants a matcher

15   }

16   }

17   }

Exercise: TestActorRef and TestKit

Page 57: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 57/61

57

 Extract the computation logic of the ComputeActor class intotwo  compute  methods

 Use a TestActorRef to test the compute methods

 Using TestKit assertions check that a ComputeActor replies

correctly to requests  TestKit assertions that might be useful (check out akka.io

documentation for more):

1   expectMsg[T](obj: T): T

2   expectMsgType[T: Manifest]

Test Probe

Page 58: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 58/61

58

 Insert test actors in order to verify message flow

1   class   ComputeActor   extends   Actor {

2   def   receive = {

3   // ...

4   case   s: String   =>

5   sender   !   compute(s)6   }

7   }

8   val   probe = TestProbe()

9   ...

10   // pass desired sender ActorRef explicitly

11   computeActor.tell("Hello world", probe.ref)

12   probe.expectMsg(11)

Exercise: Test Probe and More TestKit Assertions

Page 59: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 59/61

59

 Write an actor which upon reception of a  Query  shall fire off a  DbRequest  to an actor which has been passed to it in aconstructor argument; the reply shall go back to the originalsender, wrapped in a  Response(rsp: Any).

 Implement a test case which verifies this process, mocking theDB actor using a  TestProbe.

 Now change the implementation of the actor byadding/removing the use of futures (depending on whether

you used them in step 1 or not).

Exercise: Accumulating Computation Results

Page 60: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 60/61

60

 Extend the previous exercise to include a second service to bequeried in addition to the DB actor and use the auto-pilotfeature of the  TestProbes  to automate the mocked response

generation.   Include sleep statements simulating response latency, 1 second

each, and verify that the combined result is received within1.5 seconds.

Copyright (c) 2011, 2012 Typesafe, Inc. All rights reserved.

Page 61: Fast Track to Akka

8/9/2019 Fast Track to Akka

http://slidepdf.com/reader/full/fast-track-to-akka 61/61

61

Unless otherwise agreed, training materials may only be used foreducational and reference purposes by individual named

participants in a training course offered by Typesafe or a Typesafetraining partner. Unauthorized reproduction, redistribution, or useof this material is prohibited.