SlideShare a Scribd company logo
Distributed by Design
        Patrik Nordwall
            @patriknw
outline
         actors
     remote actors
   rise of the cluster
when the cluster grows up
What is an Actor?

• Akka's unit of computation is called an Actor
• Actors are purely reactive components:
  – a mailbox
  – behavior & state
  – scheduled to run when sent a message
• Each actor has a parent, handling its failures
Event-driven
  Thread

 Actor

 Behavior



  State
Define Actor
                        Define the message(s) the Actor
                         should be able to respond to


public class Greeting implements Serializable {
   public final String who;
   public Greeting(String who)the Actor class = who; }
                        Define { this.who
}

public class GreetingActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    int counter = 0;

        public void onReceive(Object message) {
          if (message instanceof Greeting) {
            counter++;
            log.info("Hello #" + counter + " " + ((Greeting) message).who);
          }
    }                       Define the Actor’s behavior
}
Create Actor
public class Greeting implements Serializable {
   public final String who;
   public Greeting(String who) { this.who = who; }
}

public class GreetingActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    int counter = 0;

        public void onReceive(Object message) {
          if (message instanceof Greeting) {
            counter++;
            log.info("Hello #" + counter + " " + ((Greeting) message).who);
                                                  Actor configuration
          }              Create an Actor system
    }
}

ActorSystem system = ActorSystem.create("MySystem");
ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");


              You get an ActorRef back   Create the Actor   Give it a name
Actors can form hierarchies
          Guardian System Actor


          system.actorOf(
      Foo              Bar
           new Props(Foo.class), “Foo”);

            getContext().actorOf( A
      A         C
             new Props(A.class), “A”);


B             E                          C
                             B
      D
Name resolution - like a file-system
                   Guardian System Actor

        /Foo
               Foo                   Bar

     /Foo/A
               A           C               A

 /Foo/A/B
    B                  E                       C
                                      B
               D /Foo/A/D
Send Message
public class Greeting implements Serializable {
   public final String who;
   public Greeting(String who) { this.who = who; }
}

public class GreetingActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    int counter = 0;

        public void onReceive(Object message) {
          if (message instanceof Greeting) {
            counter++;
            log.info("Hello #" + counter + " " + ((Greeting) message).who);
          }
    }
}

ActorSystem system = ActorSystem.create("MySystem");
ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");
greeter.tell(new Greeting("Charlie Parker"), null);


                   Send the message
Full example
public class Greeting implements Serializable {
   public final String who;
   public Greeting(String who) { this.who = who; }
}

public class GreetingActor extends UntypedActor {
    LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    int counter = 0;

        public void onReceive(Object message) {
          if (message instanceof Greeting) {
            counter++;
            log.info("Hello #" + counter + " " + ((Greeting) message).who);
          } else {
            unhandled(message);
          }
    }
}

ActorSystem system = ActorSystem.create("MySystem");
ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter");
greeter.tell(new Greeting("Charlie Parker"), null);
Distributa
    ble
 by Design
Akka: Distributed by Design
Node 1   Node 2
Error
Kernel
Create Actor


ActorRef greeter =
 system.actorOf(new Props(
   GreetingActor.class), "greeter");
Remote Deployment
     Just feed the ActorSystem with this configuration

                                              Configure a Remote Provider
           akka {
For the Greeter actor {
              actor
                  provider = akka.remote.RemoteActorRefProvider
                  deployment {
                     /greeter {
                       remote = akka://MySystem@machine1:2552
                     }
                  }
    Define Remote Path
              }           Protocol  Actor System Hostname   Port
           }



                       Zero code changes
Remote Lookup

ActorRef greeter =
  system.actorFor(
     "akka://MySystem@machine1:2552/user/greeter"
  );
Can you see the problem?
Fixed Addresses
akka {
  actor {
    provider =    akka.remote.RemoteActorRefProvider
    deployment    {
      /greeter    {
         remote   = akka://MySystem@machine1:2552
       }
    }
  }
}




ActorRef greeter =
  system.actorFor(
     "akka://MySystem@machine1:2552/user/greeter"
  );
Akka Cluster
Akka Cluster 2.1
                 rimental p review in 2.1
  Cluster is expe

• Gossip-based Cluster Membership
• Failure Detector
• Cluster DeathWatch
• Cluster-Aware Routers
Cluster Membership


• Node ring à la Riak / Dynamo
• Gossip-protocol for state dissemination
• Vector Clocks to detect convergence
Node ring with gossiping members
                      Member
                       Node
             Member            Member
              Node              Node



    Member                              Member
     Node                                Node

                      Gossip

    Member                              Member
     Node                                Node



             Member            Member
              Node              Node
                      Member
                       Node
Vector Clock

• Vector Clocks are used to:
 - Generate a partial ordering of events in
      a distributed system
  -   Detecting causality violations
• We use Vector Clocks to to reconcile and
  merge differences in cluster state
Gossiping Protocol

  Used for:
  –   Cluster Membership
  –   Configuration data
  –   Leader Determination
  –   Partitioning data
  –   Naming Service
Push/Pull Gossip

• Push
  – sender only sends versions (Vector Clock)
• Pull
  – receiver only asks for information for which it has
    an outdated version
• Partly biased
  – send fraction of gossip to nodes with older state
Cluster Convergence

• When each Node has seen the same Vector Clock
• unreachable nodes will fail this
• mark nodes DOWN to proceed
   – manual Ops intervention
   – automatic action
Member States

• JOINING
• UP
• LEAVING
• EXITING
• DOWN
• REMOVED
Leader

• Any node can be the leader
• Just takes the role of being a leader
• Is deterministically recognized by all nodes
  – always the first member in the sorted
     membership ring
Cluster Events

public class Listener extends UntypedActor {
  public void onReceive(Object message) {
    if (message instanceof MemberUp) {
      // ...
    }
  }
}

ActorRef listener =
 system.actorOf(new Props(Listener.class),
   "listener");

Cluster.get(system).subscribe(listener,
  MemberEvent.class);
Cluster Events
public class Listener extends UntypedActor {
  public void onReceive(Object message) {
    if (message instanceof MemberUp) {
      MemberUp mUp = (MemberUp) message;
      getContext().actorFor(mUp.address() +
        "/user/greeter").tell(
          new Greeting("Charlie Parker"), getSelf());
    }
  }
}

ActorRef listener =
 system.actorOf(new Props(Listener.class),
   "listener");

Cluster.get(system).subscribe(listener,
  MemberEvent.class);
Phi Accrual Failure Detector
                  regular messages
        A                                    B



 • B monitors A
 • Sample inter-arrival time to expect next beat
 • B measures continuum of deadness of A

            http://ddg.jaist.ac.jp/pub/HDY+04.pdf
Selective Failure Detection
                     Member
                      Node
          Member               Member
           Node                 Node



 Member                                 Member
  Node                                   Node
                   Heartbeat

Member                                  Member
 Node                                    Node



          Member
                               Member
           Node
                      Member    Node
                       Node
Selective Failure Detection
                     Member
                      Node
          Member               Member
           Node                 Node



 Member                                 Member
  Node                                   Node
                   Heartbeat

Member                                  Member
 Node                                    Node



          Member
                               Member
           Node
                      Member    Node
                       Node
Cluster DeathWatch


• Triggered by marking node «A» DOWN
 – Tell parents of their lost children on «A»
 – Kill all children of actors on «A»
 – Send Terminated for actors on «A»
Enable clustering
akka {
  actor {
    provider = "akka.cluster.ClusterActorRefProvider"
    ...
  }
 
  extensions = ["akka.cluster.Cluster"]
 
  cluster {
    seed-nodes = [
      "akka://ClusterSystem@127.0.0.1:2551",
      "akka://ClusterSystem@127.0.0.1:2552"
    ]
  }
}
Load Balancing
Routers
ActorRef routerActor =
  getContext().actorOf(
    new Props(ExampleActor.class).
     withRouter(new RoundRobinRouter(nrOfInstances))
  );
…or from config
 akka.actor.deployment {
   /path/to/actor {
     router = round-robin
     nr-of-instances = 5
   }
 }
Configure a clustered router

     akka.actor.deployment {
       /statsService/workerRouter {
         router = consistent-hashing
         nr-of-instances = 100

             cluster {
               enabled = on
               max-nr-of-instances-per-node = 3
               allow-local-routees = on
             }
         }
     }
Multi Node Testing
object MultiNodeSampleConfig extends MultiNodeConfig {
  val node1 = role("node1")
  val node2 = role("node2")
}


"A MultiNodeSample" must {

    "wait for all nodes to enter a barrier" in {
      enterBarrier("startup")
    }

}
Multi Node Testing
"send to and receive from a remote node" in {
  runOn(node1) {
    enterBarrier("deployed")
    val ponger =
      system.actorFor(node(node2) / "user" / "ponger")
    ponger ! "ping"
    expectMsg("pong")
  }

  runOn(node2) {
    system.actorOf(Props(new Actor {
      def receive = {
        case "ping" => sender ! "pong"
      }
    }), "ponger")
    enterBarrier("deployed")
  }
… when the Cluster grows up
Adaptive Load Balancing

• Metrics collected and spread
  – Heap memory
  – CPU, system load
• Adaptive Router
  – Biased random with weights based on capacity
One tree to rule them all


 • One Actor tree per node
 • Cluster tree is mapped to local sub-trees
One tree to rule them all
The Magic Sauce

• User code only sees cluster://... names
• ActorRef becomes repointable
 – local
 – remote
• Can now move actors around transparently
 – Actor encapsulation makes it possible
What does this enable?
• Actor migration
• Actor replication
• Automatic cluster partitioning
   – later also based on runtime metrics
• Node fail-over
   – first for stateless actors
   – later for stateful actors using event sourcing

         ➾ Fault Tolerance & Distribution
Cluster Specification
   doc.akka.io/docs/akka/snapshot/cluster/cluster.html


             Cluster User Guide
doc.akka.io/docs/akka/snapshot/cluster/cluster-usage-scala.html
doc.akka.io/docs/akka/snapshot/cluster/cluster-usage-java.html


                  Cluster Code
     github.com/akka/akka/tree/master/akka-cluster
get it and learn more
       http://akka.io
    http://letitcrash.com
    http://typesafe.com
E0F

More Related Content

PDF
Advanced akka features
PDF
Actor Model Akka Framework
PDF
Networks and types - the future of Akka
PPTX
Scale up your thinking
PPTX
Kotlin coroutines and spring framework
PDF
Next generation message driven systems with Akka
PDF
Akka Actors: an Introduction
PDF
Next generation actors with Akka
Advanced akka features
Actor Model Akka Framework
Networks and types - the future of Akka
Scale up your thinking
Kotlin coroutines and spring framework
Next generation message driven systems with Akka
Akka Actors: an Introduction
Next generation actors with Akka

What's hot (20)

ODP
PDF
Kotlin: a better Java
PDF
Kotlin @ Coupang Backend 2017
PDF
JUnit5 and TestContainers
PDF
Kamaelia Protocol Walkthrough
PDF
GR8Conf 2011: GPars
PDF
Distributed Consensus A.K.A. "What do we eat for lunch?"
PDF
Akka Futures and Akka Remoting
PDF
DRYing to Monad in Java8
PDF
Node Boot Camp
PDF
Creating Lazy stream in CSharp
PDF
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
PDF
Currying and Partial Function Application (PFA)
PDF
Need for Async: Hot pursuit for scalable applications
PDF
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
PDF
Java7 New Features and Code Examples
PDF
The dark side of Akka and the remedy
PDF
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
PDF
Scala active record
PDF
.NET Multithreading and File I/O
Kotlin: a better Java
Kotlin @ Coupang Backend 2017
JUnit5 and TestContainers
Kamaelia Protocol Walkthrough
GR8Conf 2011: GPars
Distributed Consensus A.K.A. "What do we eat for lunch?"
Akka Futures and Akka Remoting
DRYing to Monad in Java8
Node Boot Camp
Creating Lazy stream in CSharp
Kotlin @ Coupang Backed - JetBrains Day seoul 2018
Currying and Partial Function Application (PFA)
Need for Async: Hot pursuit for scalable applications
Fresh from the Oven (04.2015): Experimental Akka Typed and Akka Streams
Java7 New Features and Code Examples
The dark side of Akka and the remedy
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
Scala active record
.NET Multithreading and File I/O
Ad

Similar to Akka: Distributed by Design (20)

PDF
First glance at Akka 2.0
PDF
Buiilding reactive distributed systems with Akka
PDF
Reactive Programming in .Net - actorbased computing with Akka.Net
PPTX
Introduction to Akka - Atlanta Java Users Group
PDF
Apache ZooKeeper
KEY
Akka london scala_user_group
PDF
Reactive Programming in Akka
PDF
Reactive programming with akka
PDF
PDF
Scalaz 8 vs Akka Actors
PDF
Introduction to the Unreal Development Kit
PDF
Building reactive distributed systems with Akka
PDF
Testing akka-actors
PPTX
Akka Microservices Architecture And Design
PDF
A gentle introduction into AKKA and the actor model
PPSX
Moderne backends mit dem aktor programmiermodell
PPT
.NET Reflection
PPT
I phone 12
PDF
Solr @ Etsy - Apache Lucene Eurocon
PDF
Akka JUGL 2012
First glance at Akka 2.0
Buiilding reactive distributed systems with Akka
Reactive Programming in .Net - actorbased computing with Akka.Net
Introduction to Akka - Atlanta Java Users Group
Apache ZooKeeper
Akka london scala_user_group
Reactive Programming in Akka
Reactive programming with akka
Scalaz 8 vs Akka Actors
Introduction to the Unreal Development Kit
Building reactive distributed systems with Akka
Testing akka-actors
Akka Microservices Architecture And Design
A gentle introduction into AKKA and the actor model
Moderne backends mit dem aktor programmiermodell
.NET Reflection
I phone 12
Solr @ Etsy - Apache Lucene Eurocon
Akka JUGL 2012
Ad

Akka: Distributed by Design

  • 1. Distributed by Design Patrik Nordwall @patriknw
  • 2. outline actors remote actors rise of the cluster when the cluster grows up
  • 3. What is an Actor? • Akka's unit of computation is called an Actor • Actors are purely reactive components: – a mailbox – behavior & state – scheduled to run when sent a message • Each actor has a parent, handling its failures
  • 4. Event-driven Thread Actor Behavior State
  • 5. Define Actor Define the message(s) the Actor should be able to respond to public class Greeting implements Serializable { public final String who; public Greeting(String who)the Actor class = who; } Define { this.who } public class GreetingActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); int counter = 0; public void onReceive(Object message) { if (message instanceof Greeting) { counter++; log.info("Hello #" + counter + " " + ((Greeting) message).who); } } Define the Actor’s behavior }
  • 6. Create Actor public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } public class GreetingActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); int counter = 0; public void onReceive(Object message) { if (message instanceof Greeting) { counter++; log.info("Hello #" + counter + " " + ((Greeting) message).who); Actor configuration } Create an Actor system } } ActorSystem system = ActorSystem.create("MySystem"); ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter"); You get an ActorRef back Create the Actor Give it a name
  • 7. Actors can form hierarchies Guardian System Actor system.actorOf( Foo Bar new Props(Foo.class), “Foo”); getContext().actorOf( A A C new Props(A.class), “A”); B E C B D
  • 8. Name resolution - like a file-system Guardian System Actor /Foo Foo Bar /Foo/A A C A /Foo/A/B B E C B D /Foo/A/D
  • 9. Send Message public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } public class GreetingActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); int counter = 0; public void onReceive(Object message) { if (message instanceof Greeting) { counter++; log.info("Hello #" + counter + " " + ((Greeting) message).who); } } } ActorSystem system = ActorSystem.create("MySystem"); ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter"); greeter.tell(new Greeting("Charlie Parker"), null); Send the message
  • 10. Full example public class Greeting implements Serializable { public final String who; public Greeting(String who) { this.who = who; } } public class GreetingActor extends UntypedActor { LoggingAdapter log = Logging.getLogger(getContext().system(), this); int counter = 0; public void onReceive(Object message) { if (message instanceof Greeting) { counter++; log.info("Hello #" + counter + " " + ((Greeting) message).who); } else { unhandled(message); } } } ActorSystem system = ActorSystem.create("MySystem"); ActorRef greeter = system.actorOf(new Props(GreetingActor.class), "greeter"); greeter.tell(new Greeting("Charlie Parker"), null);
  • 11. Distributa ble by Design
  • 13. Node 1 Node 2 Error Kernel
  • 14. Create Actor ActorRef greeter = system.actorOf(new Props( GreetingActor.class), "greeter");
  • 15. Remote Deployment Just feed the ActorSystem with this configuration Configure a Remote Provider akka { For the Greeter actor { actor provider = akka.remote.RemoteActorRefProvider deployment { /greeter { remote = akka://MySystem@machine1:2552 } } Define Remote Path } Protocol Actor System Hostname Port } Zero code changes
  • 16. Remote Lookup ActorRef greeter = system.actorFor( "akka://MySystem@machine1:2552/user/greeter" );
  • 17. Can you see the problem?
  • 18. Fixed Addresses akka { actor { provider = akka.remote.RemoteActorRefProvider deployment { /greeter { remote = akka://MySystem@machine1:2552 } } } } ActorRef greeter = system.actorFor( "akka://MySystem@machine1:2552/user/greeter" );
  • 20. Akka Cluster 2.1 rimental p review in 2.1 Cluster is expe • Gossip-based Cluster Membership • Failure Detector • Cluster DeathWatch • Cluster-Aware Routers
  • 21. Cluster Membership • Node ring à la Riak / Dynamo • Gossip-protocol for state dissemination • Vector Clocks to detect convergence
  • 22. Node ring with gossiping members Member Node Member Member Node Node Member Member Node Node Gossip Member Member Node Node Member Member Node Node Member Node
  • 23. Vector Clock • Vector Clocks are used to: - Generate a partial ordering of events in a distributed system - Detecting causality violations • We use Vector Clocks to to reconcile and merge differences in cluster state
  • 24. Gossiping Protocol Used for: – Cluster Membership – Configuration data – Leader Determination – Partitioning data – Naming Service
  • 25. Push/Pull Gossip • Push – sender only sends versions (Vector Clock) • Pull – receiver only asks for information for which it has an outdated version • Partly biased – send fraction of gossip to nodes with older state
  • 26. Cluster Convergence • When each Node has seen the same Vector Clock • unreachable nodes will fail this • mark nodes DOWN to proceed – manual Ops intervention – automatic action
  • 27. Member States • JOINING • UP • LEAVING • EXITING • DOWN • REMOVED
  • 28. Leader • Any node can be the leader • Just takes the role of being a leader • Is deterministically recognized by all nodes – always the first member in the sorted membership ring
  • 29. Cluster Events public class Listener extends UntypedActor { public void onReceive(Object message) { if (message instanceof MemberUp) { // ... } } } ActorRef listener = system.actorOf(new Props(Listener.class), "listener"); Cluster.get(system).subscribe(listener, MemberEvent.class);
  • 30. Cluster Events public class Listener extends UntypedActor { public void onReceive(Object message) { if (message instanceof MemberUp) { MemberUp mUp = (MemberUp) message; getContext().actorFor(mUp.address() + "/user/greeter").tell( new Greeting("Charlie Parker"), getSelf()); } } } ActorRef listener = system.actorOf(new Props(Listener.class), "listener"); Cluster.get(system).subscribe(listener, MemberEvent.class);
  • 31. Phi Accrual Failure Detector regular messages A B • B monitors A • Sample inter-arrival time to expect next beat • B measures continuum of deadness of A http://ddg.jaist.ac.jp/pub/HDY+04.pdf
  • 32. Selective Failure Detection Member Node Member Member Node Node Member Member Node Node Heartbeat Member Member Node Node Member Member Node Member Node Node
  • 33. Selective Failure Detection Member Node Member Member Node Node Member Member Node Node Heartbeat Member Member Node Node Member Member Node Member Node Node
  • 34. Cluster DeathWatch • Triggered by marking node «A» DOWN – Tell parents of their lost children on «A» – Kill all children of actors on «A» – Send Terminated for actors on «A»
  • 35. Enable clustering akka { actor { provider = "akka.cluster.ClusterActorRefProvider" ... }   extensions = ["akka.cluster.Cluster"]   cluster { seed-nodes = [ "akka://ClusterSystem@127.0.0.1:2551", "akka://ClusterSystem@127.0.0.1:2552" ] } }
  • 37. Routers ActorRef routerActor = getContext().actorOf( new Props(ExampleActor.class). withRouter(new RoundRobinRouter(nrOfInstances)) );
  • 38. …or from config akka.actor.deployment { /path/to/actor { router = round-robin nr-of-instances = 5 } }
  • 39. Configure a clustered router akka.actor.deployment { /statsService/workerRouter { router = consistent-hashing nr-of-instances = 100 cluster { enabled = on max-nr-of-instances-per-node = 3 allow-local-routees = on } } }
  • 40. Multi Node Testing object MultiNodeSampleConfig extends MultiNodeConfig { val node1 = role("node1") val node2 = role("node2") } "A MultiNodeSample" must { "wait for all nodes to enter a barrier" in { enterBarrier("startup") } }
  • 41. Multi Node Testing "send to and receive from a remote node" in { runOn(node1) { enterBarrier("deployed") val ponger = system.actorFor(node(node2) / "user" / "ponger") ponger ! "ping" expectMsg("pong") } runOn(node2) { system.actorOf(Props(new Actor { def receive = { case "ping" => sender ! "pong" } }), "ponger") enterBarrier("deployed") }
  • 42. … when the Cluster grows up
  • 43. Adaptive Load Balancing • Metrics collected and spread – Heap memory – CPU, system load • Adaptive Router – Biased random with weights based on capacity
  • 44. One tree to rule them all • One Actor tree per node • Cluster tree is mapped to local sub-trees
  • 45. One tree to rule them all
  • 46. The Magic Sauce • User code only sees cluster://... names • ActorRef becomes repointable – local – remote • Can now move actors around transparently – Actor encapsulation makes it possible
  • 47. What does this enable? • Actor migration • Actor replication • Automatic cluster partitioning – later also based on runtime metrics • Node fail-over – first for stateless actors – later for stateful actors using event sourcing ➾ Fault Tolerance & Distribution
  • 48. Cluster Specification doc.akka.io/docs/akka/snapshot/cluster/cluster.html Cluster User Guide doc.akka.io/docs/akka/snapshot/cluster/cluster-usage-scala.html doc.akka.io/docs/akka/snapshot/cluster/cluster-usage-java.html Cluster Code github.com/akka/akka/tree/master/akka-cluster
  • 49. get it and learn more http://akka.io http://letitcrash.com http://typesafe.com
  • 50. E0F