Slide 1

Slide 1 text

Building Scalable Applications with the Actor Model Greg Shackles Principal Engineer, Olo @gshackles github.com/gshackles

Slide 2

Slide 2 text

Scaling: Up or Out?

Slide 3

Slide 3 text

Moore’s Law

Slide 4

Slide 4 text

OK fine, let’s get concurrent!

Slide 5

Slide 5 text

Multithreaded Programming
 
 Theory

Slide 6

Slide 6 text

Multithreaded Programming
 
 Practice

Slide 7

Slide 7 text

Oh right, concurrency is hard...

Slide 8

Slide 8 text

Amdahl’s law The theoretical speedup is always limited by the part of the task that cannot benefit from the improvement.

Slide 9

Slide 9 text

The Actor Model A better concurrency abstraction

Slide 10

Slide 10 text

What is an actor? Mailbox Behavior State

Slide 11

Slide 11 text

What can an actor do? ! Send messages ! Create other actors ! Change behavior

Slide 12

Slide 12 text

Messages ! Invoke actor behavior by sending it a message ! Messages are ○ Immutable ○ Processed one at a time, in order

Slide 13

Slide 13 text

Creating other actors

Slide 14

Slide 14 text

Everything is an actor

Slide 15

Slide 15 text

Behavior ! Switch how an actor will handle its next message ○ Referred to as becoming something ! User actor in a chat system can become: ○ Authenticating ○ Authenticated ○ Unauthenticated ○ ...and so on

Slide 16

Slide 16 text

! Actors are only referenced by address ○ Think: phone numbers, email addresses ! Code doesn’t know or care where the actor is ! Scaling from one node to thousands becomes configuration Location Transparency

Slide 17

Slide 17 text

Reactive Systems reactivemanifesto.org Responsive Message Driven Elastic Resilient

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

C#: Create a message public class Greet
 {
 public string Who { get; } public Greet(string who)
 {
 Who = who;
 }
 }

Slide 20

Slide 20 text

C#: Create an actor public class GreetingActor : ReceiveActor
 {
 public GreetingActor()
 {
 Receive(greet =>
 Console.WriteLine($"Hello {greet.Who}");
 }
 }

Slide 21

Slide 21 text

var system = ActorSystem.Create("my-system"); var greeter = system.ActorOf("greeter"); greeter.Tell(new Greet("World")); C#: Send a message

Slide 22

Slide 22 text

F#: Create a message type Message = | Greet of string

Slide 23

Slide 23 text

F#: Create an actor let handleMessage (mailbox: Actor<'a>) msg = match msg with | Greet who -> printf "Hello %s" who | _ -> ()

Slide 24

Slide 24 text

let system = ActorSystem.Create("my-system") let greeter = spawn system "greeter" (actorOf2 handleMessage) greeter

Slide 25

Slide 25 text

Supervision ! An actor can respond to subordinate actor failures with a directive to: ○ Resume the subordinate ○ Restart the subordinate ○ Stop the subordinate ○ Escalate to its own supervisor ! Actors are cheap, let them crash

Slide 26

Slide 26 text

Example Supervision Strategy protected override SupervisorStrategy SupervisorStrategy() => new OneForOneStrategy( maxNrOfRetries: 10, withinTimeRange: TimeSpan.FromSeconds(30), decider: Decider.From(ex => { if (ex is ArithmeticException) return Directive.Resume; else if (ex is NotSupportedException) return Directive.Stop; return Directive.Restart; }));

Slide 27

Slide 27 text

! Categories of messaging patterns: ○ At most once ○ At least once ○ Exactly once ! Default is at-most-once delivery ○ i.e. no guaranteed delivery Message Delivery Reliability

Slide 28

Slide 28 text

! Special type of actor that routes messages to its routees ! Built-in routing strategies ○ Round robin ○ Broadcast ○ Random ○ Consistent hashing ○ Tail chopping ○ Scatter-gather first-completed ○ Smallest mailbox Routers

Slide 29

Slide 29 text

Actor system topology is just configuration

Slide 30

Slide 30 text

Configuration
 
 Router akka.actor.deployment { /webhook-worker-pool { router = round-robin-pool nr-of-instances = 5 } }

Slide 31

Slide 31 text

Configuration
 
 Remoting actor { provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote" deployment { /remoteecho { remote = "akka.tcp://DeployTarget@localhost:8090" } } } remote { helios.tcp { port = 0 hostname = localhost } }

Slide 32

Slide 32 text

Configuration
 
 Clustering akka { actor.provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster" remote { helios.tcp { port = 8081 hostname = localhost } } cluster { seed-nodes = ["akka.tcp://ClusterSystem@localhost:8081"] roles = ["crawlerV1", "crawlerV2"] role.["crawlerV1"].min-nr-of-members = 3 } }

Slide 33

Slide 33 text

Demo github.com/gshackles/akka-samples