Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Reactive Systems with Akka

Building Reactive Systems with Akka

E0b5787d1a1935a2800e0bbffc81c196?s=128

Jonas Bonér

April 03, 2014
Tweet

Transcript

  1. Building Reactive Systems with Akka Jonas Bonér Typesafe CTO &

    co-founder Twitter: @jboner
  2. The rules of the game have changed

  3. 3 Apps in the 60s-90s were written for Apps today

    are written for
  4. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines
  5. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines
  6. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors
  7. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors
  8. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM
  9. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM
  10. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk
  11. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk
  12. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks
  13. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks
  14. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users
  15. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users
  16. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users Small data sets
  17. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users Small data sets Large data sets
  18. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users Small data sets Large data sets Latency in seconds
  19. 3 Apps in the 60s-90s were written for Apps today

    are written for Single machines Clusters of machines Single core processors Multicore processors Expensive RAM Cheap RAM Expensive disk Cheap disk Slow networks Fast networks Few concurrent users Lots of concurrent users Small data sets Large data sets Latency in seconds Latency in milliseconds
  20. None
  21. Cost Gravity is at Work X

  22. Cost Gravity is at Work X

  23. Reactive  Applications Reactive applications share four traits 5

  24. Reactive applications enrich the user experience with low latency response.

  25. Responsive • Real-time, engaging, rich and collaborative • Create an

    open and ongoing dialog with users • More efficient workflow; inspires a feeling of connectedness • Fully Reactive enabling push instead of pull 7 “The move to these technologies is already paying off. 
 Response times are down for processor intensive code–such as image 
 and PDF generation–by around 75%.”   Brian Pugh, VP of Engineering, Lucid Software
  26. Reactive applications react to 
 changes in the world around

    them.
  27. Message-Driven • Loosely coupled architecture, easier to extend, maintain, evolve

    • Asynchronous and non-blocking • Concurrent by design, immutable state • Lower latency and higher throughput 9 “Clearly, the goal is to do these operations concurrently and 
 non-blocking, so that entire blocks of seats or sections are not locked. 
 We’re able to find and allocate seats under load in less than 20ms 
 without trying very hard to achieve it.”   Andrew Headrick, Platform Architect, Ticketfly
  28. Introducing the Actor Model

  29. 11 The Actor Model

  30. 11 A computational model that embodies: The Actor Model

  31. 11 A computational model that embodies: ✓ Processing The Actor

    Model
  32. 11 A computational model that embodies: ✓ Processing ✓ Storage

    The Actor Model
  33. 11 A computational model that embodies: ✓ Processing ✓ Storage

    ✓ Communication The Actor Model
  34. 11 A computational model that embodies: ✓ Processing ✓ Storage

    ✓ Communication Supports 3 axioms—when an Actor receives a message it can: The Actor Model
  35. 11 A computational model that embodies: ✓ Processing ✓ Storage

    ✓ Communication Supports 3 axioms—when an Actor receives a message it can: 1. Create new Actors The Actor Model
  36. 11 A computational model that embodies: ✓ Processing ✓ Storage

    ✓ Communication Supports 3 axioms—when an Actor receives a message it can: 1. Create new Actors 2. Send messages to Actors it knows The Actor Model
  37. 11 A computational model that embodies: ✓ Processing ✓ Storage

    ✓ Communication Supports 3 axioms—when an Actor receives a message it can: 1. Create new Actors 2. Send messages to Actors it knows 3. Designate how it should handle the next message it receives The Actor Model
  38. The essence of an actor from Akka’s perspective 0. DEFINE

    1. CREATE 2. SEND 3. BECOME 4. SUPERVISE 12
  39. public class Greeting implements Serializable { public final String who;

    public Greeting(String who) { this.who = who; } } ! public class Greeter extends AbstractActor {{ receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchAny(unknown -> { println(“Unknown message " + unknown); }).build()); }} 0. DEFINE X
  40. public class Greeting implements Serializable { public final String who;

    public Greeting(String who) { this.who = who; } } ! public class Greeter extends AbstractActor {{ receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchAny(unknown -> { println(“Unknown message " + unknown); }).build()); }} 0. DEFINE X Define the message(s) the Actor should be able to respond to
  41. public class Greeting implements Serializable { public final String who;

    public Greeting(String who) { this.who = who; } } ! public class Greeter extends AbstractActor {{ receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchAny(unknown -> { println(“Unknown message " + unknown); }).build()); }} 0. DEFINE X Define the message(s) the Actor should be able to respond to Define the Actor class
  42. public class Greeting implements Serializable { public final String who;

    public Greeting(String who) { this.who = who; } } ! public class Greeter extends AbstractActor {{ receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchAny(unknown -> { println(“Unknown message " + unknown); }).build()); }} 0. DEFINE X Define the message(s) the Actor should be able to respond to Define the Actor class Define the Actor’s behavior
  43. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    1. CREATE
  44. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    1. CREATE Create an Actor system
  45. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    1. CREATE Create an Actor system Actor configuration
  46. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    Give it a name 1. CREATE Create an Actor system Actor configuration
  47. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    Give it a name 1. CREATE Create the Actor Create an Actor system Actor configuration
  48. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter");

    Give it a name 1. CREATE Create the Actor You get an ActorRef back Create an Actor system Actor configuration
  49. 0. DEFINE 13 case class Greeting(who: String) ! class GreetingActor

    extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s"Hello ${who}") } }
  50. 0. DEFINE 13 Define the message(s) the Actor should be

    able to respond to case class Greeting(who: String) ! class GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s"Hello ${who}") } }
  51. 0. DEFINE 13 Define the message(s) the Actor should be

    able to respond to case class Greeting(who: String) ! class GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s"Hello ${who}") } } Define the Actor class
  52. 0. DEFINE 13 Define the message(s) the Actor should be

    able to respond to case class Greeting(who: String) ! class GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s"Hello ${who}") } } Define the Actor class Define the Actor’s behavior
  53. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 1. CREATE
  54. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 1. CREATE Create an Actor system
  55. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") 1. CREATE Create an Actor system Actor configuration
  56. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") Give it a name 1. CREATE Create an Actor system Actor configuration
  57. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") Give it a name 1. CREATE Create the Actor Create an Actor system Actor configuration
  58. case class Greeting(who: String) ! class GreetingActor extends Actor with

    ActorLogging { def receive = { case Greeting(who) => log.info("Hello " + who) } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") Give it a name 1. CREATE Create the Actor You get an ActorRef back Create an Actor system Actor configuration
  59. Guardian System Actor Actors can form hierarchies

  60. Guardian System Actor system.actorOf(Props.create(Foo.class), “Foo”); Actors can form hierarchies

  61. Foo Guardian System Actor system.actorOf(Props.create(Foo.class), “Foo”); Actors can form hierarchies

  62. Foo Guardian System Actor context().actorOf(Props.create(A.class), “A”); Actors can form hierarchies

  63. A Foo Guardian System Actor context().actorOf(Props.create(A.class), “A”); Actors can form

    hierarchies
  64. A B Bar Foo C B E A D C

    Guardian System Actor Actors can form hierarchies
  65. Guardian System Actor Actors can form hierarchies

  66. Guardian System Actor system.actorOf(Props[Foo], “Foo”) Actors can form hierarchies

  67. Foo Guardian System Actor system.actorOf(Props[Foo], “Foo”) Actors can form hierarchies

  68. Foo Guardian System Actor context.actorOf(Props[A], “A”) Actors can form hierarchies

  69. A Foo Guardian System Actor context.actorOf(Props[A], “A”) Actors can form

    hierarchies
  70. A B Bar Foo C B E A D C

    Guardian System Actor Actors can form hierarchies
  71. A B Bar Foo C B E A D C

    Guardian System Actor Name resolution—like a file-system
  72. A B Bar Foo C B E A D C

    /Foo Guardian System Actor Name resolution—like a file-system
  73. A B Bar Foo C B E A D C

    /Foo /Foo/A Guardian System Actor Name resolution—like a file-system
  74. A B Bar Foo C B E A D C

    /Foo /Foo/A /Foo/A/B Guardian System Actor Name resolution—like a file-system
  75. A B Bar Foo C B E A D C

    /Foo /Foo/A /Foo/A/B /Foo/A/D Guardian System Actor Name resolution—like a file-system
  76. 2. SEND X greeter.tell(new Greeting("Charlie Parker”), sender);

  77. 2. SEND X Send the message asynchronously greeter.tell(new Greeting("Charlie Parker”),

    sender);
  78. 2. SEND X Send the message asynchronously greeter.tell(new Greeting("Charlie Parker”),

    sender); Pass in the sender ActorRef
  79. Bring it together X public class Greeting implements Serializable {

    public final String who; public Greeting(String who) { this.who = who; } } public class Greeter extends AbstractActor {{ receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchAny(unknown -> { println(“Unknown message " + unknown); }).build()); } }} ! ActorSystem system = ActorSystem.create("MySystem"); ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter"); greeter.tell(new Greeting(“Charlie Parker”));
  80. 2. SEND 17 case class Greeting(who: String) ! class GreetingActor

    extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s”Hello ${who}") } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") greeter ! Greeting("Charlie Parker")
  81. 2. SEND 17 case class Greeting(who: String) ! class GreetingActor

    extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s”Hello ${who}") } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") greeter ! Greeting("Charlie Parker") Send the message asynchronously
  82. Bring it together 18 case class Greeting(who: String) ! class

    GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) => log.info(s”Hello ${who}") } } ! val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") greeter ! Greeting("Charlie Parker")
  83. DEMO TIME A simple game of ping pong

  84. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } }
  85. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } context().become(ReceiveBuilder.
  86. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } Change the behavior context().become(ReceiveBuilder.
  87. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } Change the behavior context().become(ReceiveBuilder. match(Greeting.class, m -> {
  88. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } Change the behavior context().become(ReceiveBuilder. match(Greeting.class, m -> { println(“Go Away!”);
  89. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } Change the behavior context().become(ReceiveBuilder. match(Greeting.class, m -> { println(“Go Away!”); }).build());
  90. 3. BECOME X public class Greeter extends AbstractActor { public

    Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } Change the behavior context().become(ReceiveBuilder. match(Greeting.class, m -> { println(“Go Away!”); }).build());
  91. 3. BECOME 19 class GreetingActor extends Actor with ActorLogging {

    def receive = happy ! val happy: Receive = { case Greeting(who) => log.info(s”Hello ${who}") case Angry => context become angry } ! val angry: Receive = { case Greeting(_) => log.info("Go away!") case Happy => context become happy } }
  92. 3. BECOME 19 class GreetingActor extends Actor with ActorLogging {

    def receive = happy ! val happy: Receive = { case Greeting(who) => log.info(s”Hello ${who}") case Angry => context become angry } ! val angry: Receive = { case Greeting(_) => log.info("Go away!") case Happy => context become happy } } Redefine the behavior
  93. Reactive applications are architected 
 to handle failure at all

    levels.
  94. Resilient • Failure is embraced as a natural state in

    the app lifecycle • Resilience is a first-class construct • Failure is detected, isolated, and managed • Applications self heal 21 “The Typesafe Reactive Platform helps us maintain a very 
 aggressive development and deployment cycle, all in a fail-forward manner. 
 It’s now the default choice for developing all new services.”   Peter Hausel, VP Engineering, Gawker Media
  95. Think Vending Machine

  96. Coffee Machine Programmer Think Vending Machine

  97. Coffee Machine Programmer Inserts coins Think Vending Machine

  98. Coffee Machine Programmer Inserts coins Add more coins Think Vending

    Machine
  99. Coffee Machine Programmer Inserts coins Gets coffee Add more coins

    Think Vending Machine
  100. Coffee Machine Programmer Think Vending Machine

  101. Coffee Machine Programmer Inserts coins Think Vending Machine

  102. Coffee Machine Programmer Inserts coins Think Vending Machine Out of

    coffee beans error
  103. Coffee Machine Programmer Inserts coins Think Vending Machine Out of

    coffee beans error Wrong
  104. Coffee Machine Programmer Inserts coins Think Vending Machine

  105. Coffee Machine Programmer Inserts coins Out of coffee beans error

    Think Vending Machine
  106. Coffee Machine Programmer Service Guy Inserts coins Out of coffee

    beans error Think Vending Machine
  107. Coffee Machine Programmer Service Guy Inserts coins Out of coffee

    beans error Adds more beans Think Vending Machine
  108. Coffee Machine Programmer Service Guy Inserts coins Gets coffee Out

    of coffee beans error Adds more beans Think Vending Machine
  109. The Right Way Service Client

  110. The Right Way Service Client Request

  111. The Right Way Service Client Request Response

  112. The Right Way Service Client Request Response Validation Error

  113. The Right Way Service Client Request Response Validation Error Application

    Error
  114. The Right Way Service Client Supervisor Request Response Validation Error

    Application Error
  115. The Right Way Service Client Supervisor Request Response Validation Error

    Application Error Manages Failure
  116. None
  117. • Isolate the failure • Compartmentalize • Manage failure locally

    • Avoid cascading failures Use Bulkheads
  118. • Isolate the failure • Compartmentalize • Manage failure locally

    • Avoid cascading failures Use Bulkheads
  119. Enter Supervision

  120. Enter Supervision

  121. A B Bar Foo C B E A D C

    Automatic and mandatory supervision Supervisor hierarchies
  122. 4. SUPERVISE X class Supervisor extends UntypedActor { private SupervisorStrategy

    strategy = new OneForOneStrategy( 10, Duration.create(1, TimeUnit.MINUTES), DeciderBuilder. match(ArithmeticException.class, e -> resume()). match(NullPointerException.class, e -> restart()). matchAny( e -> escalate()). build()); ! @Override public SupervisorStrategy supervisorStrategy() { return strategy; } Every single actor has a default supervisor strategy. Which is usually sufficient. But it can be overridden.
  123. 4. SUPERVISE X class Supervisor extends UntypedActor { private SupervisorStrategy

    strategy = new OneForOneStrategy( 10, Duration.create(1, TimeUnit.MINUTES), DeciderBuilder. match(ArithmeticException.class, e -> resume()). match(NullPointerException.class, e -> restart()). matchAny( e -> escalate()). build()); ! @Override public SupervisorStrategy supervisorStrategy() { return strategy; } ActorRef worker = context.actorOf( Props.create(Worker.class), "worker"); public void onReceive(Object i) throws Exception { … } }
  124. Monitor through Death Watch X public class WatchActor extends AbstractActor

    { final ActorRef child = context().actorOf(Props.empty(), "child"); ! public WatchActor() { context().watch(child); receive(ReceiveBuilder. match(Terminated.class, t -> t.actor().equals(child), t -> { … // handle termination }).build() ); } }
  125. Monitor through Death Watch X public class WatchActor extends AbstractActor

    { final ActorRef child = context().actorOf(Props.empty(), "child"); ! public WatchActor() { context().watch(child); receive(ReceiveBuilder. match(Terminated.class, t -> t.actor().equals(child), t -> { … // handle termination }).build() ); } } Create a child actor
  126. Monitor through Death Watch X public class WatchActor extends AbstractActor

    { final ActorRef child = context().actorOf(Props.empty(), "child"); ! public WatchActor() { context().watch(child); receive(ReceiveBuilder. match(Terminated.class, t -> t.actor().equals(child), t -> { … // handle termination }).build() ); } } Create a child actor Watch it
  127. Monitor through Death Watch X public class WatchActor extends AbstractActor

    { final ActorRef child = context().actorOf(Props.empty(), "child"); ! public WatchActor() { context().watch(child); receive(ReceiveBuilder. match(Terminated.class, t -> t.actor().equals(child), t -> { … // handle termination }).build() ); } } Create a child actor Watch it Handle termination message
  128. 4. SUPERVISE 29 Every single actor has a default supervisor

    strategy. Which is usually sufficient. But it can be overridden.
  129. 4. SUPERVISE 29 Every single actor has a default supervisor

    strategy. Which is usually sufficient. But it can be overridden. class Supervisor extends Actor { override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: Exception => Escalate } ! val worker = context.actorOf(Props[Worker], name = "worker") !
  130. 4. SUPERVISE 29 class Supervisor extends Actor { override val

    supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: Exception => Escalate } ! val worker = context.actorOf(Props[Worker], name = "worker") ! def receive = { case n: Int => worker forward n } } !
  131. Cleanup & (Re)initialization 30 class Worker extends Actor { ...

    override def preRestart( reason: Throwable, message: Option[Any]) { ... // clean up before restart } override def postRestart(reason: Throwable) { ... // init after restart } }
  132. Monitor through Death Watch 31 class Watcher extends Actor {

    val child = context.actorOf(Props.empty, "child") context.watch(child) ! def receive = { case Terminated(`child`) => … // handle child termination } }
  133. Monitor through Death Watch 31 class Watcher extends Actor {

    val child = context.actorOf(Props.empty, "child") context.watch(child) ! def receive = { case Terminated(`child`) => … // handle child termination } } Create a child actor
  134. Monitor through Death Watch 31 class Watcher extends Actor {

    val child = context.actorOf(Props.empty, "child") context.watch(child) ! def receive = { case Terminated(`child`) => … // handle child termination } } Create a child actor Watch it
  135. Monitor through Death Watch 31 class Watcher extends Actor {

    val child = context.actorOf(Props.empty, "child") context.watch(child) ! def receive = { case Terminated(`child`) => … // handle child termination } } Create a child actor Watch it Handle termination message
  136. Reactive applications scale up 
 and down to meet demand.

  137. Elastic • Elasticity and Scalability to embrace the Cloud •

    Adaptive Scale on Demand • Clustered servers support joining and leaving of nodes • More cost-efficient utilization of hardware 33 “Our traffic can increase by as much as 100x for 15 minutes each day. 
 Until a couple of years ago, noon was a stressful time. 
 Nowadays, it’s usually a non-event.”   Eric Bowman, VP Architecture, Gilt Groupe
  138. 34 Scale OUT Scale UP

  139. 34 Essentially the same thing

  140. 35 1. Minimize Contention 2. Maximize Locality of Reference We

    need to
  141. 36 Share NOTHING Design

  142. Fully event-driven apps are a necessity X Amdahl’s Law will

    hunt you down
  143. Define a router X ActorRef router = context().actorOf( new RoundRobinPool(5).props(Props.create(Worker.class)),

    “router”)
  144. Define a router 37 val router = context.actorOf( RoundRobinPool(5).props(Props[Worker])), “router”)

  145. …or from config 38 akka.actor.deployment { /service/router { router =

    round-robin-pool resizer { lower-bound = 12 upper-bound = 15 } } }
  146. Turn on clustering 39 akka { actor { provider =

    "akka.cluster.ClusterActorRefProvider" ... } cluster { seed-nodes = [ “akka.tcp://ClusterSystem@127.0.0.1:2551", “akka.tcp://ClusterSystem@127.0.0.1:2552" ] auto-down = off } }
  147. Use clustered routers 40 akka.actor.deployment  {      /service/master  {

             router  =  consistent-­‐hashing-­‐pool          nr-­‐of-­‐instances  =  100   !        cluster  {              enabled  =  on              max-nr-of-instances-per-node = 3              allow-­‐local-­‐routees  =  on              use-­‐role  =  compute          }      }   }
  148. Use clustered routers 40 akka.actor.deployment  {      /service/master  {

             router  =  consistent-­‐hashing-­‐pool          nr-­‐of-­‐instances  =  100   !        cluster  {              enabled  =  on              max-nr-of-instances-per-node = 3              allow-­‐local-­‐routees  =  on              use-­‐role  =  compute          }      }   } Or perhaps use an AdaptiveLoadBalancingPool
  149. Use clustered pub-sub 41

  150. Use clustered pub-sub 41 class Subscriber extends Actor { val

    mediator = DistributedPubSubExtension(context.system).mediator mediator ! Subscribe(“content”, self) def receive = { … } }
  151. Use clustered pub-sub 41 class Publisher extends Actor { val

    mediator = DistributedPubSubExtension(context.system).mediator def receive = { case in: String => mediator ! Publish("content", in.toUpperCase) } }
  152. • Cluster Membership • Cluster Pub/Sub • Cluster Leader •

    Clustered Singleton • Cluster Roles • Cluster Sharding 42 Other Akka Cluster features
  153. • Supports two different models: • Command Sourcing • Event

    Sourcing • Great for implementing • durable actors • replication • CQRS etc. • Messages persisted to Journal and replayed on restart 43 Use Akka Persistence
  154. X Command Sourcing Event Sourcing

  155. X Command Sourcing Event Sourcing write-ahead-log

  156. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command
  157. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation
  158. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery
  159. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation
  160. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation events cannot fail
  161. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation events cannot fail allows retroactive changes to the business logic
  162. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation events cannot fail allows retroactive changes to the business logic fixing the business logic will not affect persisted events
  163. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation events cannot fail allows retroactive changes to the business logic fixing the business logic will not affect persisted events naming: represent intent, imperative
  164. X Command Sourcing Event Sourcing write-ahead-log derive events from a

    command same behavior during recovery as normal operation only state-changing behavior during recovery persisted before validation events cannot fail allows retroactive changes to the business logic fixing the business logic will not affect persisted events naming: represent intent, imperative naming: things that have completed, verbs in past tense
  165. Akka  Persistence  Webinar Domain Events • Things that have completed,

    facts • Immutable • Verbs in past tense • CustomerRelocated • CargoShipped • InvoiceSent “State transitions are an important part of our problem space and should be modeled within our domain.”   Greg Young, 2008
  166. Akka  Persistence  Webinar Life beyond Distributed Transactions: an Apostate’s Opinion

    Position Paper by Pat Helland “In general, application developers simply do not implement large scalable applications assuming distributed transactions.”   Pat Helland http://www-­‐db.cs.wisc.edu/cidr/cidr2007/papers/cidr07p15.pdf
  167. Akka  Persistence  Webinar Consistency boundary • An Actor is can

    define an Aggregate Root • Each containing one or more Entities • Aggregate Root is the Transactional Boundary • Strong consistency within an Aggregate • Eventual consistency between Aggregates • No limit to scalability
  168. DEMO TIME Persist a game of ping pong

  169. None
  170. http://reactivemanifesto.org

  171. Typesafe Activator http://typesafe.com/platform/getstarted

  172. 48 Typesafe Reactive Platform • Actors are asynchronous and communicate

    via message passing • Supervision and clustering in support of fault tolerance • Purely asynchronous and non-blocking web frameworks • No container required, no inherent bottlenecks in session management • Asynchronous and immutable programming constructs • Composable abstractions enabling simpler concurrency and parallelism
  173. Reactive is being adopted across
 a wide range of industries.

  174. 50 Finance Internet/Social Media Mfg/Hardware Government Retail

  175. Questions?

  176. ©Typesafe 2014 – All Rights Reserved