Akka 2.0: towards new heights
                        @remeniuk




                                    emilypolar@flickr
Location Transparency
You’re doing your regular coding job for a local
environment, and get ability to run your system in a
distributed environment any time for free.
RMI, EJB, CORBA, SOAP,
XML-RPC, Thrift
RMI, EJB, CORBA, SOAP,
XML-RPC, Thrift

are easy, but ultimately
flawed!

Fail under network
partitioning and partial
failure...
RMI, EJB, CORBA, SOAP,
XML-RPC

are easy, but ultimately
flawed!
 It’s time for RPC to retire.
Fail under network
partitioning and partial   Steve Vinovsky
failure...
RMI, EJB, CORBA, SOAP,     Akka*
XML-RPC
                           Simple toolkit for building
are easy, but ultimately   distributed, scalable,
flawed!                    fault-tolerant systems

Fail under network         • actors / transactors
partitioning and partial   • supervisors
failure...                 • routing and dispatching
                           • STM for better shared
                             stated concurrency
                           • much more…
class HelloWorldActor extends Actor {
   def receive = {
       case msg => self reply (msg + " World")
   }
}

                                      LocalActorRef


val myActor = actorOf[HelloWorldActor].start()


val result = myActor !! “message”
Dispatcher stuffs actor[-s] with messages


class ActorA extends Actor {
  self.dispatcher = someDispatcher
  ...
}

class ActorB extends Actor {
  self.dispatcher = someDispatcher
  ...
}
Actor Registry knows about all the local
actors
registry.actorFor(id)
registry.actorFor(uuid)
registry.actorsFor(classOf[...])
etc.
making actor accessible remotely
remote.start("localhost", 9999).register(
     "hello-service", actorOf[HelloWorldActor])



                                 RemoteActorRef


val actor = remote.actorFor(
      "hello-service", "localhost", 9999)

val result = actor !! "Hello"
Moreover, there could be a pool of
actors behind the ActorRef
class MyLoadBalancer extends Actor with LoadBalancer {

    val pinger = actorOf(new Actor {
           def receive = { case x => println("Pinger: " + x) } }).start()

    val ponger = actorOf(new Actor {
          def receive = { case x => println("Ponger: " + x) } }).start()

    val seq = new CyclicIterator[ActorRef](List(pinger,ponger))

}
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
Fault tolerance
Groups of linked, supervised actors define subsystems:
those actors crash and restart together
val supervisor = Supervisor(
 SupervisorConfig(
  AllForOneStrategy(List(classOf[Exception]), 3, 1000),
  Supervise(actorOf[MyActor1], Permanent) ::
  Supervise(actorOf[MyActor2], Permanent) ::
Nil))


actor1.link(actor2)
supervisor.link(actor2)
Akka 2.0
In Akka 2.0 there’re no
                  local vs.
remote actors anymore. All the
actors are distributed (clustered, routed)
the new level of transparency
brand new akka-cluster

in Soviet Russia by default, all the actors are local



but when you pass a config
cluster magic starts to happen
cluster magic
•   actors migration
•   actors replication
•   cluster-wide routing
•   adaptive load balancing
•   distributed actor registry
•   leader election
•   much more…
New important concepts:

• actor address
• deployment config
[behind the scenes]
                          actor clustering
get deployment config


is scope
                                            LocalActorRef
local?


                     Distributed Registry   add to local actor registry

                    store serilized actor
                    factory in ZooKeeper
                                                 create               create actor on
                                                  actor                    node


                                                ClusteredActorRef / RoutedActorRef
       ZooKeeper is used for storing
       cluster configs, serialized actor
       factories, metrics, etc.
Using clustered actor
akka.enabled-modules = ["cluster"]
akka.event-handler-level = "WARNING"
akka.actor.deployment.service-hello.router = "round-robin"
akka.actor.deployment.service-hello.clustered.replication-factor = 2
akka.actor.deployment.service-hello.clustered.preferred-nodes =
["node:node1","node:node3"]




node.start()
helloActor = actorOf[HelloWorld]("service-hello“)
[Akka 1.x] PROBLEM: synchronization of
registries in a distributed network?




POSSIBLE SOLUTION: https://github.com/remeniuk/akka-easyscale
Distributed Registry


Node A

node.store(“my-actor", classOf[MyActor], serializerFor(classOf[MyActor]))




Node B

node.use(“my-actor")
Actor Props

actorOf(Props[TestActor]
      .withDispatcher(new PinnedDispatcher())
      .withFaultHandler(
      OneForOneStrategy(List(classOf[Exception]), 5, 1000))



actorOf(Props(self ⇒ {
      case “hello" ⇒ self tryReply “hello!"
})
Composable Futures




              !!
                     *HINT: (actor ? message).get
Composable Futures


val future1 = for {
       a <- (actor ? message1).mapTo[String]
       b <- (actor ? message2).mapTo[String]
} yield a + b

val future2 = (actor ? Message3).map(_.toString)

val future3 = Futures.find[String](_.isEmpty)(
                                       Seq(future1, future2))
BONUS: multi-jvm testing with
scalatest in specs2

 https://github.com/typesafehub/sbt-multi-jvm

 https://github.com/jboner/akka/tree/master/akk
 a-cluster/src/multi-jvm

 https://github.com/remeniuk/sbt-multi-jvm
GO AND TRY IT!

> git clone https://github.com/jboner/akka
> sbt

First glance at Akka 2.0

  • 1.
    Akka 2.0: towardsnew heights @remeniuk emilypolar@flickr
  • 2.
  • 3.
    You’re doing yourregular coding job for a local environment, and get ability to run your system in a distributed environment any time for free.
  • 4.
    RMI, EJB, CORBA,SOAP, XML-RPC, Thrift
  • 5.
    RMI, EJB, CORBA,SOAP, XML-RPC, Thrift are easy, but ultimately flawed! Fail under network partitioning and partial failure...
  • 6.
    RMI, EJB, CORBA,SOAP, XML-RPC are easy, but ultimately flawed! It’s time for RPC to retire. Fail under network partitioning and partial Steve Vinovsky failure...
  • 7.
    RMI, EJB, CORBA,SOAP, Akka* XML-RPC Simple toolkit for building are easy, but ultimately distributed, scalable, flawed! fault-tolerant systems Fail under network • actors / transactors partitioning and partial • supervisors failure... • routing and dispatching • STM for better shared stated concurrency • much more…
  • 8.
    class HelloWorldActor extendsActor { def receive = { case msg => self reply (msg + " World") } } LocalActorRef val myActor = actorOf[HelloWorldActor].start() val result = myActor !! “message”
  • 9.
    Dispatcher stuffs actor[-s]with messages class ActorA extends Actor { self.dispatcher = someDispatcher ... } class ActorB extends Actor { self.dispatcher = someDispatcher ... }
  • 10.
    Actor Registry knowsabout all the local actors
  • 11.
  • 12.
  • 13.
    remote.start("localhost", 9999).register( "hello-service", actorOf[HelloWorldActor]) RemoteActorRef val actor = remote.actorFor( "hello-service", "localhost", 9999) val result = actor !! "Hello"
  • 14.
    Moreover, there couldbe a pool of actors behind the ActorRef class MyLoadBalancer extends Actor with LoadBalancer { val pinger = actorOf(new Actor { def receive = { case x => println("Pinger: " + x) } }).start() val ponger = actorOf(new Actor { def receive = { case x => println("Ponger: " + x) } }).start() val seq = new CyclicIterator[ActorRef](List(pinger,ponger)) }
  • 15.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 16.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 17.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 18.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 19.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 20.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 21.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 22.
    Fault tolerance Groups oflinked, supervised actors define subsystems: those actors crash and restart together
  • 23.
    val supervisor =Supervisor( SupervisorConfig( AllForOneStrategy(List(classOf[Exception]), 3, 1000), Supervise(actorOf[MyActor1], Permanent) :: Supervise(actorOf[MyActor2], Permanent) :: Nil)) actor1.link(actor2) supervisor.link(actor2)
  • 24.
  • 25.
    In Akka 2.0there’re no local vs. remote actors anymore. All the actors are distributed (clustered, routed)
  • 26.
    the new levelof transparency
  • 27.
    brand new akka-cluster inSoviet Russia by default, all the actors are local but when you pass a config cluster magic starts to happen
  • 28.
    cluster magic • actors migration • actors replication • cluster-wide routing • adaptive load balancing • distributed actor registry • leader election • much more…
  • 29.
    New important concepts: •actor address • deployment config
  • 30.
    [behind the scenes] actor clustering get deployment config is scope LocalActorRef local? Distributed Registry add to local actor registry store serilized actor factory in ZooKeeper create create actor on actor node ClusteredActorRef / RoutedActorRef ZooKeeper is used for storing cluster configs, serialized actor factories, metrics, etc.
  • 31.
    Using clustered actor akka.enabled-modules= ["cluster"] akka.event-handler-level = "WARNING" akka.actor.deployment.service-hello.router = "round-robin" akka.actor.deployment.service-hello.clustered.replication-factor = 2 akka.actor.deployment.service-hello.clustered.preferred-nodes = ["node:node1","node:node3"] node.start() helloActor = actorOf[HelloWorld]("service-hello“)
  • 36.
    [Akka 1.x] PROBLEM:synchronization of registries in a distributed network? POSSIBLE SOLUTION: https://github.com/remeniuk/akka-easyscale
  • 37.
    Distributed Registry Node A node.store(“my-actor",classOf[MyActor], serializerFor(classOf[MyActor])) Node B node.use(“my-actor")
  • 38.
    Actor Props actorOf(Props[TestActor] .withDispatcher(new PinnedDispatcher()) .withFaultHandler( OneForOneStrategy(List(classOf[Exception]), 5, 1000)) actorOf(Props(self ⇒ { case “hello" ⇒ self tryReply “hello!" })
  • 39.
    Composable Futures !! *HINT: (actor ? message).get
  • 40.
    Composable Futures val future1= for { a <- (actor ? message1).mapTo[String] b <- (actor ? message2).mapTo[String] } yield a + b val future2 = (actor ? Message3).map(_.toString) val future3 = Futures.find[String](_.isEmpty)( Seq(future1, future2))
  • 41.
    BONUS: multi-jvm testingwith scalatest in specs2 https://github.com/typesafehub/sbt-multi-jvm https://github.com/jboner/akka/tree/master/akk a-cluster/src/multi-jvm https://github.com/remeniuk/sbt-multi-jvm
  • 42.
    GO AND TRYIT! > git clone https://github.com/jboner/akka > sbt