29
Scaling Web Apps with Akka Maciej Matyjas London Scala User Group Skills Matter 2010 July 14

Scaling Web Apps with Akka

Embed Size (px)

Citation preview

Page 1: Scaling Web Apps with Akka

 Scaling Web Apps with Akka 

Maciej Matyjas London Scala User Group Skills Matter2010 July 14

Page 2: Scaling Web Apps with Akka

“ Simple Scalability,     Fault-Tolerance, Concurrency &     Remoting through Actors”akkasource.org

Page 3: Scaling Web Apps with Akka

Scaling Web Apps with Akka

High AvailabilityQuick Page LoadsFast Reads/Writes

Characteristics TechniquesHardware Load BalancingCachingPartitioning Queues/MessagingReplication CDN

Page 4: Scaling Web Apps with Akka

Scaling Web Apps with Akka

Page 5: 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

Page 6: Scaling Web Apps with Akka

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

Page 7: Scaling Web Apps with Akka

Actors Model of Computing

Defined in 1963 by Carl Hewitt

Used by Erlang to support reliability (99.9999999% uptime)

Page 8: Scaling Web Apps with Akka

Actors Model of Computing

"encapsulates state and behavior into a lightweight process/thread" - Jonas BonérAsynchronous message passing between ActorsMessages are immutableSynchronized mailboxMailbox is read with pattern matchingNo shared stateNo locksSafe concurrency

Page 9: Scaling Web Apps with Akka

No shared state +

No locks =

Safe concurrency

Page 10: Scaling Web Apps with Akka

ErlangScala Thread basedScala Event basedLift ActorsAkka

Actors Model Implementations

Page 11: Scaling Web Apps with 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"}.

Page 12: Scaling Web Apps with Akka

Scala Thread Based Actorsimport scala.actor.Actorimport 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?")}

Page 13: Scaling Web Apps with Akka

Scala Event Based Actorsimport scala.actor.Actorimport 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?")}

Page 14: Scaling Web Apps with Akka

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!")}

Page 15: Scaling Web Apps with Akka

Akka Actorsimport se.scalablesolutions.akka.actor.Actorcase 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!")}

Page 16: Scaling Web Apps with Akka

Leverage Multi-Core and Distributed Cloud Infrastructure

Millions of lightweight actors on commodity hardware

Safe Concurrency

Remote Actors

Page 17: Scaling Web Apps with Akka

Leverage Multi-Core and Distributed Cloud Infrastructure: Remote Actorsimport se.scalablesolutions.akka.remote.RemoteNode spawnRemote[MyActor](host, port) spawnLinkRemote[MyActor](host, port)startLinkRemote(myActor, host, port)

Page 18: Scaling Web Apps with Akka

Handle Failure Gracefully

"Let it Crash"Actor exceptions w/out supervision do not behave well Remote Actors w/out supervision are unmanaged Linking ActorsSupervisor

Manages linked ActorsNotified when linked Actor crashesOneForOneAllForOne

Works with Remote Actors

Page 19: Scaling Web Apps with Akka

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 }}

Page 20: Scaling Web Apps with Akka

Manage Transactions

Software Transactional Memory (STM)Thanks Clojure!Addresses fundamental weakness of Actors ModelHello Shared State!Transactional but still no locksIn memoryMap, Vector, & Ref throw exceptions if modified outside of transactionACI but no D

Transactors Transactional ActorsActors + STMIf Actor's writes clash, rollback memory and retried

Page 21: Scaling Web Apps with Akka

Manage Transactions: Transactorsimport se.scalablesolutions.akka.actor.Transactorimport 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)}

Page 22: Scaling Web Apps with Akka

NoSQL & Distributed Data Stores

Pluggable Storage Back EndsCassandraRedisMongoDBOthers...

Brings the D in ACIDWorks with STM and Transactors

Page 23: Scaling Web Apps with Akka

NoSQL & Distributed Data Stores: Casssandraimport se.scalablesolutions.akka._import stm.Transaction.Local._import persistence.cassandra._ val map = CassandraStorage.newMap(myId)// map += "myKey" -> Value(someSuch) // exceptionatomic { map += "myKey" -> Value(someSuch)}

Page 24: Scaling Web Apps with Akka

Flexible Dispatch Strategies

Default is Single-threaded, Event-based dispatcher Work-stealing, Event-based Reactor-base, Event-drivenThread-basedEvent-based

Page 25: Scaling Web Apps with Akka

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}

Page 26: Scaling Web Apps with Akka

Here Comes the Code Demo Time!

Page 27: Scaling Web Apps with Akka

Versions

Scala 2.8.0.RC6Lift 2.0-scala2.8.0-SNAPSHOTAkka 2.8.0.RC3 0.9.1sbt 0.7.4ensime master on github.com

Page 28: Scaling Web Apps with Akka

AlternativesBefore Drinking the Kool-Aid or Flogging Your Fav Tool

scalaz FunctionalJavaGParallelizerKilimActorFoundryActors GuildJetlangActoromFan Actors

Other Actor Impls More Options JVM

Fork/JoinESBNettyHawtDispatch

ErlangRabbitMQHadoopOpenMPMPI

Page 29: Scaling Web Apps with Akka

Questions About Akka?

http://akkasource.orghttp://groups.google.com/group/akka-userCourse at Skills Matter Oct 13-14 LSUG talk on Oct 13Ask me:

@matyjas [email protected]