First glance at Akka 2.0
-
Upload
vasil-remeniuk -
Category
Technology
-
view
6.656 -
download
0
description
Transcript of First glance at Akka 2.0
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!
Fail under network
partitioning and partial
failure...
It’s time for RPC to retire.
Steve Vinovsky
RMI, EJB, CORBA, SOAP,
XML-RPC
are easy, but ultimately
flawed!
Fail under network
partitioning and partial
failure...
Akka*
Simple toolkit for building
distributed, scalable,
fault-tolerant systems
• actors / transactors
• supervisors
• routing and dispatching
• STM for better shared
stated concurrency
• much more…
class HelloWorldActor extends Actor {
def receive = {
case msg => self reply (msg + " World")
}
}
val myActor = actorOf[HelloWorldActor].start()
val result = myActor !! “message”
LocalActorRef
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])
val actor = remote.actorFor(
"hello-service", "localhost", 9999)
val result = actor !! "Hello"
RemoteActorRef
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
Distributed Registry
get deployment config
is scope
local?
add to local actor registry
store serilized actor
factory in ZooKeepercreate
actor
create actor on
node
ClusteredActorRef / RoutedActorRef
LocalActorRef
ZooKeeper is used for storing
cluster configs, serialized actor
factories, metrics, etc.
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“)
Using clustered actor
[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