Upload
bsantoshraj
View
238
Download
0
Embed Size (px)
Citation preview
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
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
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 3/61
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
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
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 6/61
Manage system overload
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 7/617
Scale up & out
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 8/61
Replicate and distribute
for Fault-Tolerance
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 9/619
Architecture
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 10/6110
Architecture
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 11/61
11
Architecture
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
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 13/61
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 14/61
14
What is an Actor?
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 15/61
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 16/61
16
What is an Actor?
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 17/61
A M d l f C
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
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
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
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
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
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: !
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
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
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
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 }
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 28/61
Send: ? and ask
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
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
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
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
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
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 34/61
g
Two blocking threads
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 35/61
g
What we really want
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 36/61
Using Futures with Actors
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
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
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
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
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
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 42/61
Handling multiple Futures
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
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
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
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
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
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
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>]]
8/9/2019 Fast Track to Akka
http://slidepdf.com/reader/full/fast-track-to-akka 50/61
Exercise: More robust cancellation
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
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
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
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
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
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
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
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
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
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.
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.