Scaling Web Apps with Akka 
Maciej Matyjas
London Scala User Group
Skills Matter
2010 July 14
“ Simple Scalability, 
    Fault-Tolerance, Concurrency & 
    Remoting through Actors”
akkasource.org
Scaling Web Apps with Akka

Characteristics      Techniques
 High Availability    Hardware
 Quick Page Loads     Load Balancing
 Fast Reads/Writes    Caching
                      Partitioning
                      Queues/Messaging
                      Replication
                      CDN
Scaling Web Apps with Akka
Scaling Web Apps with Akka

  Range of mountains in Sweden

  Open Source Project

  Written in Scala with Scala/Java APIs
Scaling Web Apps with Akka

  Actors Model

  Multi-Core and Cloud Infrastructure

  Graceful Failure a la Erlang OTP

  Transactions a la Clojure

  NoSQL and Distributed Data Stores

  Flexible Dispatch Strategies
Actors Model of Computing


 Defined in 1963 by Carl Hewitt

 Used by Erlang to support reliability (99.9999999% uptime)
Actors Model of Computing

 "encapsulates state and behavior into a lightweight
 process/thread" - Jonas Bonér
 Asynchronous message passing between Actors
 Messages are immutable
 Synchronized mailbox
 Mailbox is read with pattern matching
 No shared state
 No locks
 Safe concurrency
No shared state
        +
    No locks
        =
Safe concurrency
Actors Model Implementations

 Erlang
 Scala Thread based
 Scala Event based
 Lift Actors
 Akka
Erlang Actors Example
-module(mypackage).

myErlangActor() ->
receive
{msgType, Msg} ->
  io:format(" p n", [Msg]),
  myErlangActor()
Other ->
  io:format("wholy canoli, this is unmatched! n"),
  myErlangActor()
end.

c(mypackage).
Pid = spawn(fun mypackage:myErlangActor/0).
Pid ! {msgType, "Erlang is for the discerning programmer"}.
Scala Thread Based Actors
import scala.actor.Actor
import scala.actor.Actor._

case class Message(msg: String)

class AnActor extends Actor {
   def act() = receive {
     case Message(m) => println(m)
     case _ => println("unknown message")
   }
}

class Director {
   val myActor = new AnActor
   myActor.start
   myActor ! Message("threedz can haz block?")
}
Scala Event Based Actors
import scala.actor.Actor
import scala.actor.Actor._

case class Message(msg: String)

class AnActor extends Actor {
   def act() = loop {
                 react {
                   case Message(m) => println(m)
                   case _ => println("unknown message")
}}}

class Director {
   val myActor = new AnActor
   myActor.start
   myActor ! Message("eventz iz lightweight?")
}
Lift Actors

case class Message(msg: String)

class AnActor extends LiftActor {
 def messageHandler = {
   case Message(m) => println(m)
   case _ => println("unknown message")
}}

class Director {
   val myActor = new AnActor
   myActor ! Message("Lift Actors is lightest & rulz!")
}
Akka Actors
import se.scalablesolutions.akka.actor.Actor
case class Message(msg: String)

class AnActor extends Actor {
   def receive = {
     case Message(m) => println(m)
     case _ => println("unknown message")
   }
}

class Director {
   val myActor = Actor.actorOf[AnActor]
   myActor.start
   myActor ! Message("akkastic!")
}
Leverage Multi-Core and Distributed
Cloud Infrastructure
 Millions of lightweight actors on commodity hardware

 Safe Concurrency

 Remote Actors
Leverage Multi-Core and Distributed
Cloud Infrastructure: Remote Actors
import se.scalablesolutions.akka.remote.RemoteNode

spawnRemote[MyActor](host, port)

spawnLinkRemote[MyActor](host, port)
startLinkRemote(myActor, host, port)
Handle Failure Gracefully

  "Let it Crash"
  Actor exceptions w/out supervision do not behave well
  Remote Actors w/out supervision are unmanaged
  Linking Actors
  Supervisor
     Manages linked Actors
     Notified when linked Actor crashes
     OneForOne
     AllForOne
  Works with Remote Actors
Handle Failure Gracefully: Supervisor
 val supervisor = Supervisor(
  SupervisorConfig(
   RestartStrategy(OneForOne, 3, 1000, List(classOf[Exception])),
  Supervise(
   actorOf[MyActor],
   LifeCycle(Permanent)) ::
  Nil))

supervisor.link(actorOf[MyActor])

class MyActor extends Actor {
    self.lifeCycle = Some(LifeCycle(Permanent))
    override def preRestart(reason: Throwable) {
      // clean things up
   }
}
Manage Transactions
 Software Transactional Memory (STM)
    Thanks Clojure!
    Addresses fundamental weakness of Actors Model
    Hello Shared State!
    Transactional but still no locks
    In memory
    Map, Vector, & Ref throw exceptions if modified outside
    of transaction
    ACI but no D
 Transactors
    Transactional Actors
    Actors + STM
    If Actor's writes clash, rollback memory and retried
Manage Transactions: Transactors
import se.scalablesolutions.akka.actor.Transactor
import se.scalablesolutions.akka.stm._

class MyActor extends Transactor {
   def receive = {
      case Increment(counter) => counter.swap(counter.get + 1)
   }
}

class Director {
   lazy val counter = Ref(0)
   //counter.swap(7) // blows up, cannot mutate outside transaction
   myActor ! Increment(counter)
}
NoSQL & Distributed Data Stores

 Pluggable Storage Back Ends
     Cassandra
     Redis
     MongoDB
     Others...
 Brings the D in ACID
 Works with STM and Transactors
NoSQL & Distributed Data Stores:
Casssandra
import se.scalablesolutions.akka._
import stm.Transaction.Local._
import persistence.cassandra._

val map = CassandraStorage.newMap(myId)
// map += "myKey" -> Value(someSuch) // exception
atomic {
   map += "myKey" -> Value(someSuch)
}
Flexible Dispatch Strategies

 Default is Single-threaded, Event-based dispatcher
 Work-stealing, Event-based
 Reactor-base, Event-driven
 Thread-based
 Event-based
Flexible Dispatch Strategies

class MyActor extends Actor {

  self.dispatcher = Dispatchers.
newExecutorBasedEventDrivenDispatche(name)

    dispatcher
       .withNewThreadPoolWithBoundedBlockingQueue(100)
       .setCorePoolSize(16)
       .setMaxPoolSize(128)
       .setKeepAliveTimeInMillis(60000)
       .setRejectionPolicy(new CallerRunsPolicy)
       .buildThreadPool
}
Here Comes the Code
Demo Time!
Versions

 Scala 2.8.0.RC6
 Lift 2.0-scala2.8.0-SNAPSHOT
 Akka 2.8.0.RC3 0.9.1
 sbt 0.7.4
 ensime master on github.com
Alternatives
Before Drinking the Kool-Aid or Flogging Your Fav Tool


 Other Actor Impls                More Options
    scalaz                          JVM
    FunctionalJava                      Fork/Join
    GParallelizer                       ESB
    Kilim                               Netty
    ActorFoundry                        HawtDispatch
    Actors Guild                    Erlang
    Jetlang                         RabbitMQ
    Actorom                         Hadoop
    Fan Actors                      OpenMP
                                    MPI
Questions About Akka?

 http://akkasource.org
 http://groups.google.com/group/akka-user
 Course at Skills Matter Oct 13-14
 LSUG talk on Oct 13
 Ask me:
     @matyjas
     matyjas@gmail.com

Scaling Web Apps with Akka

  • 1.
     Scaling Web Appswith Akka  Maciej Matyjas London Scala User Group Skills Matter 2010 July 14
  • 2.
    “ Simple Scalability,     Fault-Tolerance, Concurrency &      Remoting through Actors” akkasource.org
  • 3.
    Scaling Web Appswith Akka Characteristics Techniques High Availability Hardware Quick Page Loads Load Balancing Fast Reads/Writes Caching Partitioning Queues/Messaging Replication CDN
  • 4.
  • 5.
    Scaling Web Appswith Akka Range of mountains in Sweden Open Source Project Written in Scala with Scala/Java APIs
  • 6.
    Scaling Web Appswith Akka Actors Model Multi-Core and Cloud Infrastructure Graceful Failure a la Erlang OTP Transactions a la Clojure NoSQL and Distributed Data Stores Flexible Dispatch Strategies
  • 7.
    Actors Model ofComputing Defined in 1963 by Carl Hewitt Used by Erlang to support reliability (99.9999999% uptime)
  • 8.
    Actors Model ofComputing "encapsulates state and behavior into a lightweight process/thread" - Jonas Bonér Asynchronous message passing between Actors Messages are immutable Synchronized mailbox Mailbox is read with pattern matching No shared state No locks Safe concurrency
  • 9.
    No shared state + No locks = Safe concurrency
  • 10.
    Actors Model Implementations Erlang Scala Thread based Scala Event based Lift Actors Akka
  • 11.
    Erlang Actors Example -module(mypackage). myErlangActor()-> receive {msgType, Msg} -> io:format(" p n", [Msg]), myErlangActor() Other -> io:format("wholy canoli, this is unmatched! n"), myErlangActor() end. c(mypackage). Pid = spawn(fun mypackage:myErlangActor/0). Pid ! {msgType, "Erlang is for the discerning programmer"}.
  • 12.
    Scala Thread BasedActors import scala.actor.Actor import scala.actor.Actor._ case class Message(msg: String) class AnActor extends Actor { def act() = receive { case Message(m) => println(m) case _ => println("unknown message") } } class Director { val myActor = new AnActor myActor.start myActor ! Message("threedz can haz block?") }
  • 13.
    Scala Event BasedActors import scala.actor.Actor import scala.actor.Actor._ case class Message(msg: String) class AnActor extends Actor { def act() = loop { react { case Message(m) => println(m) case _ => println("unknown message") }}} class Director { val myActor = new AnActor myActor.start myActor ! Message("eventz iz lightweight?") }
  • 14.
    Lift Actors case classMessage(msg: String) class AnActor extends LiftActor { def messageHandler = { case Message(m) => println(m) case _ => println("unknown message") }} class Director { val myActor = new AnActor myActor ! Message("Lift Actors is lightest & rulz!") }
  • 15.
    Akka Actors import se.scalablesolutions.akka.actor.Actor caseclass Message(msg: String) class AnActor extends Actor { def receive = { case Message(m) => println(m) case _ => println("unknown message") } } class Director { val myActor = Actor.actorOf[AnActor] myActor.start myActor ! Message("akkastic!") }
  • 16.
    Leverage Multi-Core andDistributed Cloud Infrastructure Millions of lightweight actors on commodity hardware Safe Concurrency Remote Actors
  • 17.
    Leverage Multi-Core andDistributed Cloud Infrastructure: Remote Actors import se.scalablesolutions.akka.remote.RemoteNode spawnRemote[MyActor](host, port) spawnLinkRemote[MyActor](host, port) startLinkRemote(myActor, host, port)
  • 18.
    Handle Failure Gracefully "Let it Crash" Actor exceptions w/out supervision do not behave well Remote Actors w/out supervision are unmanaged Linking Actors Supervisor Manages linked Actors Notified when linked Actor crashes OneForOne AllForOne Works with Remote Actors
  • 19.
    Handle Failure Gracefully:Supervisor val supervisor = Supervisor( SupervisorConfig( RestartStrategy(OneForOne, 3, 1000, List(classOf[Exception])), Supervise( actorOf[MyActor], LifeCycle(Permanent)) :: Nil)) supervisor.link(actorOf[MyActor]) class MyActor extends Actor { self.lifeCycle = Some(LifeCycle(Permanent)) override def preRestart(reason: Throwable) { // clean things up } }
  • 20.
    Manage Transactions SoftwareTransactional Memory (STM) Thanks Clojure! Addresses fundamental weakness of Actors Model Hello Shared State! Transactional but still no locks In memory Map, Vector, & Ref throw exceptions if modified outside of transaction ACI but no D Transactors Transactional Actors Actors + STM If Actor's writes clash, rollback memory and retried
  • 21.
    Manage Transactions: Transactors importse.scalablesolutions.akka.actor.Transactor import se.scalablesolutions.akka.stm._ class MyActor extends Transactor { def receive = { case Increment(counter) => counter.swap(counter.get + 1) } } class Director { lazy val counter = Ref(0) //counter.swap(7) // blows up, cannot mutate outside transaction myActor ! Increment(counter) }
  • 22.
    NoSQL & DistributedData Stores Pluggable Storage Back Ends Cassandra Redis MongoDB Others... Brings the D in ACID Works with STM and Transactors
  • 23.
    NoSQL & DistributedData Stores: Casssandra import se.scalablesolutions.akka._ import stm.Transaction.Local._ import persistence.cassandra._ val map = CassandraStorage.newMap(myId) // map += "myKey" -> Value(someSuch) // exception atomic { map += "myKey" -> Value(someSuch) }
  • 24.
    Flexible Dispatch Strategies Default is Single-threaded, Event-based dispatcher Work-stealing, Event-based Reactor-base, Event-driven Thread-based Event-based
  • 25.
    Flexible Dispatch Strategies classMyActor extends Actor { self.dispatcher = Dispatchers. newExecutorBasedEventDrivenDispatche(name) dispatcher .withNewThreadPoolWithBoundedBlockingQueue(100) .setCorePoolSize(16) .setMaxPoolSize(128) .setKeepAliveTimeInMillis(60000) .setRejectionPolicy(new CallerRunsPolicy) .buildThreadPool }
  • 26.
    Here Comes theCode Demo Time!
  • 27.
    Versions Scala 2.8.0.RC6 Lift 2.0-scala2.8.0-SNAPSHOT Akka 2.8.0.RC3 0.9.1 sbt 0.7.4 ensime master on github.com
  • 28.
    Alternatives Before Drinking theKool-Aid or Flogging Your Fav Tool Other Actor Impls More Options scalaz JVM FunctionalJava Fork/Join GParallelizer ESB Kilim Netty ActorFoundry HawtDispatch Actors Guild Erlang Jetlang RabbitMQ Actorom Hadoop Fan Actors OpenMP MPI
  • 29.
    Questions About Akka? http://akkasource.org http://groups.google.com/group/akka-user Course at Skills Matter Oct 13-14 LSUG talk on Oct 13 Ask me: @matyjas matyjas@gmail.com