Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Designing Reactive Systems with Akka

2,742 views

Published on

The latest buzzword in the web service community is “reactive.” We dig beneath the surface of this word and show how you can use Scala and Akka to build systems that are responsive, resilient, elastic, and message-driven.

Published in: Software
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Designing Reactive Systems with Akka

  1. 1. DESIGNING REACTIVE SYSTEMS WITH AKKA Thomas Lockney • @tlockney http://thomas.lockney.net OSCON 2015 • Portland, Oregon
  2. 2. WHO AM I? Engineering at Nike+/CDT Past experience at Cisco, Janrain, Simple, IBM/ Tivoli, etc. Founder of PNWScala, PDXScala, & various events/groups
  3. 3. OUR MODERN WORLD Distributed Mobile Unreliable, frequent disconnects “The Cloud”
  4. 4. OUR MODERN WORLD
  5. 5. OUR MODERN WORLD
  6. 6. OUR MODERN WORLD
  7. 7. REACTIVE SOFTWARE Message-driven Resilient Elastic Responsive
  8. 8. APPLYING OLD PATTERNS TO NEW CHALLENGES
  9. 9. INTRODUCING AKKA Scalable concurrency toolkit Actor model implementation (more on this shortly) Fault tolerance Distributed by default
  10. 10. THE ACTOR MODEL Message-passing Encapsulation of state and behavior Mutable state is protected Sequential internally, asynchronous between actors
  11. 11. A SIMPLE EXAMPLE case class Greeting(name: String) 
 class GreetingActor extends Actor with ActorLogging {
 def receive = {
 case Greeting(name) ⇒
 log.info("Hello, {}", name)
 }
 }
 
 val system = ActorSystem("MyExampleSystem")
 val greeter = system.actorOf(Props[GreetingActor],
 name = "greeter")
 greeter ! Greeting("Thomas")
  12. 12. case class 
 class log.info( } }
 
 val val name = greeter case class Greeting(name: String) 
 A SIMPLE EXAMPLE def receive = {
 case Greeting(name) ⇒
 log.info("Hello, {}", name)
 }
 val system = ActorSystem("MyExampleSystem")
 val greeter = system.actorOf(Props[GreetingActor],
 name = "greeter") greeter ! Greeting("Thomas") protocol behavior actor system actor creation sending a message case class 
 class log.info( } }
 
 val val name = greeter case class Greeting(name: String) 
 class GreetingActor extends Actor with ActorLogging {
 def receive = {
 case Greeting(name) ⇒
 log.info("Hello, {}", name)
 }
 }
 
 val system = ActorSystem("MyExampleSystem")
 val greeter = system.actorOf(Props[GreetingActor],
 name = "greeter")
 greeter ! Greeting("Thomas")
  13. 13. WHAT AKKA PROVIDES Actor hierarchy with supervision Flexible message routing Configurable scheduling via dispatchers
  14. 14. THE HIERARCHY
  15. 15. THE HIERARCHY Guardian
  16. 16. THE HIERARCHY Guardian User hierarchy
  17. 17. THE HIERARCHY Guardian User hierarchy User actors
  18. 18. SUPERVISION
  19. 19. SUPERVISION /a/c/f fails
  20. 20. SUPERVISION supervisor restarts child
  21. 21. SUPERVISION
  22. 22. SUPERVISOR EXAMPLE case object DieNow
 case class DomainException(failureMsg: String) extends Exception(failureMsg)
 
 class Child extends Actor {
 import context.dispatcher 
 scheduler.scheduleOnce(Random.nextInt(5000).milliseconds, self, DieNow)
 
 def receive = {
 case DieNow ⇒ throw new DomainException("R.I.P.")
 }
 }
  23. 23. SUPERVISOR EXAMPLE class TopLevel extends Actor {
 def receive = Actor.emptyBehavior
 
 override def preStart() = { context.actorOf(Props[Child]) }
 
 override def supervisorStrategy =
 OneForOneStrategy(maxNrOfRetries = 2, withinTimeRange = 10.seconds) {
 case DomainException(msg) ⇒ Restart
 }
 }
  24. 24. DESIGNING WITH AKKA Protocols Workflow Failure Handling
  25. 25. –Merriam-Webster “a system of rules that explain the correct conduct and procedures to be followed in formal situations.” Protocol
  26. 26. PROTOCOLS Define the interaction between actors Specify clear boundaries of responsibility Encode external representation of state at a point in time Demarcate success and failure clearly
  27. 27. AVERY SIMPLE PROTOCOL trait Response
 case class Success(res: Array[Byte]) extends Response
 case class Failure(err: String) extends Response
  28. 28. WORKFLOW Work-pulling Pipelines
  29. 29. WORK-PULLING Enables a simple form of back- pressure Decouples failure handling from the workflow
  30. 30. WORK-PULLING
  31. 31. EXAMPLE case object RequestWork
 case class Work(id: String, data: String) class Worker(queue: ActorRef) extends Actor with ActorLogging {
 
 override def preStart = {
 queue ! RequestWork
 }
 
 def receive = {
 case w:Work ⇒
 log.info(w.data.toUpperCase)
 queue ! RequestWork
 }
 
 }
  32. 32. EXAMPLE class Queuer extends Actor { 
 val queuedWork = Queue.empty[Work]
 val requestors = Queue.empty[ActorRef]
 def receive = {
 case RequestWork if (queuedWork.nonEmpty) ⇒
 sender ! queuedWork.dequeue
 case RequestWork ⇒
 requestors.enqueue(sender)
 case w:Work if (requestors.nonEmpty) ⇒
 requestors.dequeue ! w
 case w:Work ⇒
 queuedWork.enqueue(w)
 } 
 }
  33. 33. PIPELINES Commonly found in data processing applications Distinct phases of data responsibility May span one or more systems Often have radically varying scaling needs
  34. 34. PIPELINES Each phase has its own failure domain Back-pressure is managed through the chain The simplified view
  35. 35. PIPELINES Each phase has a failure domain Back-pressure is still managed through the chain The more typical view
  36. 36. PIPELINES Often just an extension of more basic patterns Work-pulling is a common component Keep an eye on Akka Streams!
  37. 37. FAULT-TOLERANCE Circuit-breakers Isolate key systems Fault isolation and failure-domains Restrict the size of the impact
  38. 38. CIRCUIT-BREAKER Isolate important components Avoid cascading failures
  39. 39. CIRCUIT-BREAKER class FailingActor extends Actor {
 import context.dispatcher
 system.scheduler.scheduleOnce(Random.nextInt(5000).milliseconds, self, Die)
 def receive = {
 case Die ⇒
 throw new Exception("I've fallen and I can't get up!")
 case s: String ⇒ sender ! s.toUpperCase
 }
 }
  40. 40. CIRCUIT-BREAKER val breaker =
 new CircuitBreaker(context.system.scheduler,
 maxFailures = 5,
 callTimeout = 10.seconds,
 resetTimeout = 1.minute)
 
 def receive = {
 case Tick ⇒
 val in = Random.alphanumeric.take(10).mkString
 breaker.withCircuitBreaker(toUpper ? in) pipeTo self
 case s:String ⇒
 log.info("Received: {}", s)
 }
  41. 41. FAILURE-DOMAINS AND FAULT ISOLATION
  42. 42. FAILURE-DOMAINS AND FAULT ISOLATION These are failure-domains
  43. 43. FAILURE-DOMAINS AND FAULT ISOLATION
  44. 44. FAILURE-DOMAINS AND FAULT ISOLATION These don’t have to care
  45. 45. THANKYOU! QUESTIONS?

×