Concurrency in Scala - the Akka way


Published on

  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Concurrency in Scala - the Akka way

  1. 1. CONCURRENCY IN SCALA THE AKKA WAY Yardena Meymann Sr. Software Architect at VMware February 2013
  2. 2. SCALABILITY• The amount of work grows – BIG.*
  3. 3. SCALABILITY• Scale up and out without breaking down
  4. 4. SCALA• Programming language for JVM• Functional and Object-Oriented• Type-safe• Powerful• Concise• Extensible• Interoperable with Java
  5. 5. AKKA• Akka is a toolkit and runtime for building highly concurrent, distributed, and fault tolerant event-driven applications on the JVM• Provides unified programming model for concurrency, distribution and fault-tolerance
  6. 6. ACTORSActor is a fundamental unit of computation(Carl Hewitt 1973)• Local state, isolated from the world• Sends messages to other actors• Reacts to received messages• Actors usually come in systems
  7. 7. ACTORS• Elastic – grow and shrink on demand• Lightweight (2.7 M per GB RAM)• Hot deploy – change behavior at runtime• Local or distributed
  8. 8. EXAMPLE - SCOTCHDOG• Inspired by Monit• Cross-platform, JVM-based (Scala+Akka)• Configured with list of services• Starts and stops services• Ensures that monitored services are up: checks periodically and starts if necessary
  9. 9. HOW IS THIS GOING TO WORK• Actor per service• Actor for the watchdog
  10. 10. ACTOR HIERARCHY Watchdog Service 1 Service 2 Service 3
  11. 11. AKKA ACTOR HIERARCHY root system user Watchdog system actors Service 1 Service 2 Service 3
  12. 12. WHY THE HIERARCHY IS IMPORTANT• Fault-tolerance• “Let it crash”• Supervisor can resume, restart, terminate the subordinate; it can also escalate the failure• One-for-one and one-for-all strategies
  13. 13. LET’S START WITH MESSAGES• Service commands • start • stop • is started? • monitor/unmonitor• Watchdog commands • start • add service • do *** to a specified service • …
  14. 14. SERVICE COMMANDSsealed trait ServiceCommandcase object Start extends ServiceCommandcase object Stop extends ServiceCommandcase object IsStarted extends ServiceCommand…• Commands need to be immutable objects• Case classes and objects make excellent messages
  15. 15. WATCHDOG COMMANDScase object StartWatchingcase class AddService(config: ServiceConfig)case class PerServiceCommand( service: String, command: ServiceCommand)...
  16. 16. SENDING MESSAGES• tell (a.k.a bang, or ! operator) sends a message asynchronously and return immediately service ! Start• ask (a.k.a ? operator) sends a message asynchronously and returns a Future representing a possible reply service ? IsStarted
  17. 17. HANDLING MESSAGES• Define actor classclass Service(config: ServiceConfig) extends Actor …• Actor gives us • ability to create other actors • access to self • access to sender of last message • lifecycle hooks
  18. 18. HANDLING MESSAGESDefine receive method within Actor classdef receive = { case Start => //perform start action case Stop => //perform stop action case IsStarted => { //call isStarted action and capture the result sender ! result //reply - return the result to sender }}Heavily uses Scala’s pattern matching
  19. 19. CREATING ACTORS• class Watchdog extends Actor …• val system = ActorSystem(“Scotchdog”)• val watchdog = system.actorOf( Props[Watchdog], name = “watchdog”)• watchdog is an ActorRef• we used default constructor• Props allows customizations of actor behavior, such as the dispatcher (execution strategy). We used the default one
  20. 20. HANDLING MESSAGES - WATCHDOGdef receive = { case AddService(config) => { val service = context.actorOf(Props(new Service(config)), service ! Monitor } case PerServiceCommand(service, command) => context.actorFor(service) forward command …
  21. 21. ACTOR REFERENCES• Top level actors are created with system, child actors are created with parent actor’s context• Existing actors can be found with context/system actorFor• ActorRef can be sent to another actor
  22. 22. FUTURESval future = watchdog ? PerServiceCommand(“myserver", IsStarted)There are several ways to obtain the value:• val result = Await.result(future, 5 seconds). asInstanceOf[Boolean]• future onComplete { case Success(value: Boolean) => … case Failure(_) => … }
  23. 23. MORE ADVANCED EXAMPLE• We want the watchdog to return a combined status of all services – “up” if all services are up, otherwise “down” • We will define: val services = new scala.collection.mutable.HashSet[String] within Watchdog class • It is safe to have mutable state within an actor! • When adding services: services +=
  24. 24. MORE ADVANCED EXAMPLEdef receive = { case Status => { val responses = for (child <- services; serviceActor = context.actorFor(child)); future = serviceActor ? IsStarted) yield future.asInstanceOf[Future[Boolean]] sender ! Future.reduce(responses)(_ && _) } …
  25. 25. SCHEDULER• We want to check periodically if a service is up, and report the status at any time• For this purpose we can use Akka’s built-in scheduler• …
  26. 26. SCHEDULER EXAMPLEclass ServiceMonitor(config: ServiceConfig) extends Actor with ActorLogging { var status = false var polling: Option[Cancellable] = None def receive = { case IsStarted => sender ! status case Monitor => polling = Some(scheduler.schedule(Duration.Zero, config.interval, self, Tick)) case Tick => sender ? config.isStarted onSuccess { case res: Boolean => status = res } case UnMonitor => polling.foreach(_.cancel) …
  27. 27. FURTHER IMPROVEMENTS• In practice, the service actor is more complex: for example, we don’t want to start a service again if it is already started or is starting up now• To address this we use Akka’s Finite State Machine actors, a.k.a FSM• This is a topic for a longer talk, so for now…
  28. 28. CONCLUSIONS• Akka makes concurrency (and distribution, which we didn’t cover) easier• Programming with actors require a paradigm shift, may be challenging at first, but worth it• There is more to Akka then we’ve covered• If you like Akka, but want to program in Java, you can use Java API• Akka integrates with tools like Spring, Apache Camel and ZeroMQ
  29. 29. RESOURCES•••••• akka-patterns/• Coming soon
  30. 30. THANK YOU