Building Reactive Applications with Akka & Java 8 - Bonèr
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Building Reactive Applications with Akka & Java 8 - Bonèr

  • 581 views
Uploaded on

Slides from Jonas Bonèr talk @ codemotion roma 2014

Slides from Jonas Bonèr talk @ codemotion roma 2014

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
581
On Slideshare
581
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
37
Comments
0
Likes
5

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Building Reactive Applications with Akka & Java 8 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. Cost Gravity is at Work 5
  • 21. Cost Gravity is at Work 5
  • 22. Reactive  Applications Reactive applications share four traits 6
  • 23. Reactive applications react to 
 changes in the world around them.
  • 24. Event-Driven • Loosely coupled architecture, easier to extend, maintain, evolve • Asynchronous and non-blocking • Concurrent by design, immutable state • Lower latency and higher throughput 8 “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
  • 25. Introducing the Actor Model
  • 26. 10 The Actor Model
  • 27. 10 A computational model that embodies: The Actor Model
  • 28. 10 A computational model that embodies: ✓ Processing The Actor Model
  • 29. 10 A computational model that embodies: ✓ Processing ✓ Storage The Actor Model
  • 30. 10 A computational model that embodies: ✓ Processing ✓ Storage ✓ Communication The Actor Model
  • 31. 10 A computational model that embodies: ✓ Processing ✓ Storage ✓ Communication Supports 3 axioms—when an Actor receives a message it can: The Actor Model
  • 32. 10 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
  • 33. 10 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
  • 34. 10 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
  • 35. The essence of an actor from Akka’s perspective 0. DEFINE 1. CREATE 2. SEND 3. BECOME 4. SUPERVISE 11
  • 36. 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 12
  • 37. 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 12 Define the message(s) the Actor should be able to respond to
  • 38. 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 12 Define the message(s) the Actor should be able to respond to Define the Actor class
  • 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 12 Define the message(s) the Actor should be able to respond to Define the Actor class Define the Actor’s behavior
  • 40. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter"); 1. CREATE
  • 41. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter"); 1. CREATE Create an Actor system
  • 42. ActorSystem system = ActorSystem.create("MySystem"); ! ActorRef greeter = system.actorOf(Props.create(Greeter.class), “greeter"); 1. CREATE Create an Actor system Actor configuration
  • 43. 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
  • 44. 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
  • 45. 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
  • 46. Guardian System Actor Actors can form hierarchies
  • 47. Guardian System Actor system.actorOf(Props.create(Foo.class), “Foo”); Actors can form hierarchies
  • 48. Foo Guardian System Actor system.actorOf(Props.create(Foo.class), “Foo”); Actors can form hierarchies
  • 49. Foo Guardian System Actor context().actorOf(Props.create(A.class), “A”); Actors can form hierarchies
  • 50. A Foo Guardian System Actor context().actorOf(Props.create(A.class), “A”); Actors can form hierarchies
  • 51. A B BarFoo C B E A D C Guardian System Actor Actors can form hierarchies
  • 52. A B BarFoo C B E A D C Guardian System Actor Name resolution—like a file-system
  • 53. A B BarFoo C B E A D C /Foo Guardian System Actor Name resolution—like a file-system
  • 54. A B BarFoo C B E A D C /Foo /Foo/A Guardian System Actor Name resolution—like a file-system
  • 55. A B BarFoo C B E A D C /Foo /Foo/A /Foo/A/B Guardian System Actor Name resolution—like a file-system
  • 56. A B BarFoo C B E A D C /Foo /Foo/A /Foo/A/B /Foo/A/D Guardian System Actor Name resolution—like a file-system
  • 57. 2. SEND 16 greeter.tell(new Greeting("Charlie Parker”), sender);
  • 58. 2. SEND 16 Send the message asynchronously greeter.tell(new Greeting("Charlie Parker”), sender);
  • 59. 2. SEND 16 Send the message asynchronously greeter.tell(new Greeting("Charlie Parker”), sender); Pass in the sender ActorRef
  • 60. Bring it together 17 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”));
  • 61. 3. BECOME 18 public class Greeter extends AbstractActor { public Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } }
  • 62. 3. BECOME 18 public class Greeter extends AbstractActor { public Greeter { receive(ReceiveBuilder. match(Greeting.class, m -> { println(“Hello " + m.who); }). matchEquals(“stop" -> { ! ! ! ! }).build(); } } context().become(ReceiveBuilder.
  • 63. 3. BECOME 18 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.
  • 64. 3. BECOME 18 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 -> {
  • 65. 3. BECOME 18 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!”);
  • 66. 3. BECOME 18 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());
  • 67. 3. BECOME 18 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());
  • 68. Reactive applications are architected 
 to handle failure at all levels.
  • 69. 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 20 “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
  • 70. Think Vending Machine
  • 71. Coffee Machine Programmer Think Vending Machine
  • 72. Coffee Machine Programmer Inserts coins Think Vending Machine
  • 73. Coffee Machine Programmer Inserts coins Add more coins Think Vending Machine
  • 74. Coffee Machine Programmer Inserts coins Gets coffee Add more coins Think Vending Machine
  • 75. Coffee Machine Programmer Think Vending Machine
  • 76. Coffee Machine Programmer Inserts coins Think Vending Machine
  • 77. Coffee Machine Programmer Inserts coins Think Vending Machine Out of coffee beans error
  • 78. Coffee Machine Programmer Inserts coins Think Vending Machine Out of coffee beans error Wrong
  • 79. Coffee Machine Programmer Inserts coins Think Vending Machine
  • 80. Coffee Machine Programmer Inserts coins Out of coffee beans error Think Vending Machine
  • 81. Coffee Machine Programmer Service Guy Inserts coins Out of coffee beans error Think Vending Machine
  • 82. Coffee Machine Programmer Service Guy Inserts coins Out of coffee beans error Adds more beans Think Vending Machine
  • 83. Coffee Machine Programmer Service Guy Inserts coins Gets coffee Out of coffee beans error Adds more beans Think Vending Machine
  • 84. The Right Way ServiceClient
  • 85. The Right Way ServiceClient Request
  • 86. The Right Way ServiceClient Request Response
  • 87. The Right Way ServiceClient Request Response Validation Error
  • 88. The Right Way ServiceClient Request Response Validation Error Application Error
  • 89. The Right Way ServiceClient Supervisor Request Response Validation Error Application Error
  • 90. The Right Way ServiceClient Supervisor Request Response Validation Error Application Error Manages Failure
  • 91. • Isolate the failure • Compartmentalize • Manage failure locally • Avoid cascading failures Use Bulkheads
  • 92. • Isolate the failure • Compartmentalize • Manage failure locally • Avoid cascading failures Use Bulkheads
  • 93. Enter Supervision
  • 94. Enter Supervision
  • 95. A B BarFoo C B E A D C Automatic and mandatory supervision Supervisor hierarchies
  • 96. 4. SUPERVISE 28 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.
  • 97. 4. SUPERVISE 28 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 { … } }
  • 98. Monitor through Death Watch 29 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() ); } }
  • 99. Monitor through Death Watch 29 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
  • 100. Monitor through Death Watch 29 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
  • 101. Monitor through Death Watch 29 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
  • 102. Reactive applications scale up 
 and down to meet demand.
  • 103. Scalable • Scalability and elasticity to embrace the Cloud • Leverage all cores via asynchronous programming • Clustered servers support joining and leaving of nodes • More cost-efficient utilization of hardware 31 “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
  • 104. Define a router 32 ActorRef router = context().actorOf( new RoundRobinPool(5).props(Props.create(Worker.class)), “router”)
  • 105. …or from config 33 akka.actor.deployment { /service/router { router = round-robin-pool resizer { lower-bound = 12 upper-bound = 15 } } }
  • 106. Turn on clustering 34 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 } }
  • 107. Use clustered routers 35 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          }      }   }
  • 108. Use clustered routers 35 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
  • 109. • Cluster Membership • Cluster Pub/Sub • Cluster Leader • Clustered Singleton • Cluster Roles • Cluster Sharding 36 Other Akka Cluster features
  • 110. • Supports two different models: • Command Sourcing — at least once • Event Sourcing — at most once • Great for implementing • durable actors • replication • CQRS etc. • Messages persisted to Journal and replayed on restart 37 Use Akka Persistence
  • 111. 38 Command Sourcing Event Sourcing
  • 112. 38 Command Sourcing Event Sourcing write-ahead-log
  • 113. 38 Command Sourcing Event Sourcing write-ahead-log derive events from a command
  • 114. 38 Command Sourcing Event Sourcing write-ahead-log derive events from a command same behavior during recovery as normal operation
  • 115. 38 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
  • 116. 38 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
  • 117. 38 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
  • 118. 38 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
  • 119. 38 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
  • 120. 38 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
  • 121. 38 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
  • 122. 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
  • 123. Akka  Persistence  Webinar Consistency boundary • Aggregate Root is the Transactional Boundary • Strong consistency within an Aggregate • Eventual consistency between Aggregates • No limit to scalability
  • 124. 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
  • 125. Reactive applications enrich the user experience with low latency response.
  • 126. 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 43 “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
  • 127. http://reactivemanifesto.org
  • 128. Typesafe Activator http://typesafe.com/platform/getstarted
  • 129. Questions?
  • 130. ©Typesafe 2014 – All Rights Reserved