creating scalable message driven solutions akkadotnet

45
CREATING SCALABLE MESSAGE-DRIVEN SOLUTIONS (WITH AKKA.NET) David Hoerster

Upload: david-hoerster

Post on 12-Apr-2017

672 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Creating scalable message driven solutions akkadotnet

CREATING SCALABLE MESSAGE-DRIVEN

SOLUTIONS (WITH AKKA.NET)

David Hoerster

Page 2: Creating scalable message driven solutions akkadotnet

ABOUT ME 5-Time .NET (Visual C#) MVP (April 2011) Sr. Solutions Architect at Confluence One of the organizers for Pittsburgh TechFest (http://pghtechfest.com) Organizer of Pittsburgh Reactive Dev Group (http://meetup.com/reactive)

Past President of Pittsburgh .NET Users Group Twitter - @DavidHoerster Blog – http://blog.agileways.com Email – [email protected]

Page 3: Creating scalable message driven solutions akkadotnet

AGENDA Messages as Part of Application Design Being Reactive What the Actor Model Provides Hello Akka.NET Working with Akka.NET Cross-Process Actor Systems (Akka.Remote)

Page 4: Creating scalable message driven solutions akkadotnet

CQRS Command Query Responsibility Segregation Coined by Greg Young

Evolution of CQS (Command Query Separation) Coined by Bertrand Meyer

Both revolve around the separation of writes (command) and reads (query)

CQS is more at the unit level CQRS is at the bounded context level, or so

Page 5: Creating scalable message driven solutions akkadotnet

MESSAGES The core of CQRS Messages Communication from the service layer to the domain via commands Command handlers could also update the underlying repository

As actions happen, events are raised Event handlers could issue other commands Event handlers could update the underlying repository

Page 6: Creating scalable message driven solutions akkadotnet

MESSAGES Regardless of how it’s implemented, communication between application parts is via messages

Not only helps communicate intent of the action “PublishWidget”, “ExpireWorkItem”, “UpdateDefinition”, “DefinitionUpdated”

But allows for remote handling of messages Queue, REST payload, etc.

Page 7: Creating scalable message driven solutions akkadotnet

MESSAGES ARE KEY TO BEING REACTIVE

Page 8: Creating scalable message driven solutions akkadotnet

SO? So how does this affect my system design?

Let’s consider some procedural pitfalls

Page 9: Creating scalable message driven solutions akkadotnet

WORD COUNTER EXAMPLE Simple program to count the occurrences of words in a document

Print out the top 25 words and their counts at the end

Can be accomplished easily via procedural code

Page 10: Creating scalable message driven solutions akkadotnet

WORD COUNTER EXAMPLE

Page 11: Creating scalable message driven solutions akkadotnet

WORD COUNTER EXAMPLE What if you wanted to spread out the counting load?

What if you wanted to scale out to other nodes/processes/machines?

Fault tolerance, concurrent actions, etc.?

Page 12: Creating scalable message driven solutions akkadotnet

BUILDING CONCURRENT APPS In word counter, may need to spawn some threads

Lock some critical sections, etc.

The system becomes responsible for knowing everything going on Very Proactive (not Reactive!) system

Page 13: Creating scalable message driven solutions akkadotnet

SIDE NOTE: REACTIVE VS. PROACTIVE Isn’t proactive a good thing?

A system taking upon itself to check state is proactive It’s doing too much

A reactive system reacts to events that occur It’s doing just the right amount

Page 14: Creating scalable message driven solutions akkadotnet

SIDE NOTE: REACTIVE VS. PROACTIVE Isn’t proactive a good thing?

A system taking upon itself to check state is proactive It’s doing too much

A reactive system reacts to events that occur It’s doing just the right amount

System

EvtEvt

System

EvtEvt

Proactive

Reactive

Page 15: Creating scalable message driven solutions akkadotnet

REAL WORLD SCENARIO Loosely structured data

Multiple files to combine

Operations to perform during the projection process

Page 16: Creating scalable message driven solutions akkadotnet

REAL WORLD SCENARIO

File File File

Join

Op

Join/End

Page 17: Creating scalable message driven solutions akkadotnet

REAL WORLD SCENARIO Number of “steps”

May need some sub-steps

Can be broken down into individual pieces Actors

Communicate via messages for loose coupling

Page 18: Creating scalable message driven solutions akkadotnet

REAL WORLD SCENARIO Actually looks like this:

Multiple sources

Several transforms

Several joins

Configurable

Page 19: Creating scalable message driven solutions akkadotnet

ACTOR MODEL Actor Model is a system made of small units of concurrent computation Formulated in the early 70’s

Each unit is an actor

Communicates to each other via messages

Actors can have children, which they can supervise

Page 20: Creating scalable message driven solutions akkadotnet

WHAT IS AN ACTOR? Class that encapsulates state and behavior State can be persisted (Akka.Persistence) Behavior can be switched (Become/Unbecome)

Has a mailbox to receive messages Ordered delivery by default Queue

Can create child actors Has a supervisory strategy for child actors How to handle misbehaving children

Are always thread safe Have a lifecycle Started, stopped, restarted

Page 21: Creating scalable message driven solutions akkadotnet

AKKA.NET Akka.NET is an open source framework Actor Model for .NET

Port of Akka (for JVM/Scala)

http://getakka.net

NuGet package – search for Akka.Net (not the first result usually!)

Page 22: Creating scalable message driven solutions akkadotnet

STARTING WITH AKKA.NET Akka.NET is a hierarchical system

Root of the system is ActorSystem

Expensive to instantiate – create and hold!

ActorSystem can then be used to create Actors

Page 23: Creating scalable message driven solutions akkadotnet

CREATING AN ACTOR An Actor has a unique address Can be accessed/communicated to like a URI

Call ActorOf off ActorSystem, provide it a name URI (actor path) is created hierarchically

Actor Path = akka://myName/user/announcer

Page 24: Creating scalable message driven solutions akkadotnet

SENDING A MESSAGE Messages are basis of actor communication Should be IMMUTABLE!!!

“Tell” an actor a message Async call

Immutable!!

Page 25: Creating scalable message driven solutions akkadotnet

RECEIVING A MESSAGE Create your Actor

Derive from ReceiveActor

In constructor, register your message subscriptions

Page 26: Creating scalable message driven solutions akkadotnet

RECEIVING A MESSAGE Each actor has a mailbox

Messages are received in the actor’s mailbox (queue)

Actor is notified that there’s a message It receives the message Takes it out of the mailbox Next one is queued up

Ordered delivery by default Other mailboxes (like Priority) that are out-of-order

Actor

Mai

lbox

Msg

Page 27: Creating scalable message driven solutions akkadotnet

HELLO AKKA.NET Demo

Page 28: Creating scalable message driven solutions akkadotnet

CREATING CHILDREN Best to call ActorOf to get an IActorRef

Create a static Props creator

Actor path is relative to parent’s actor path

akka://myDemo/user/countChocula/{childName}

When creating a child, good idea to name it So you can reference it later!

Page 29: Creating scalable message driven solutions akkadotnet

WORD COUNTER WITH ACTORS Program sends StartCount message to CountSupervisor CountSupervisor, for each line, sends line to one of 5 LineCounterActors (ReadLineForCounting message)

LineCounterActor counts the word in that line Tells the Sender (CountSupervisor) the results (MappedList message) CountSupervisor aggregates results of MappedList messages When all lines complete, CountSupervisor sends each LineActor a Complete message

LineCounterActor cleans up and sends CountSupervisor Complete When all LineCounterActors are Complete, CountSupervisor prints out top 25 words

Page 30: Creating scalable message driven solutions akkadotnet

MAP-REDUCE DEMO

Page 31: Creating scalable message driven solutions akkadotnet

ROUTING Map Reduce example used Round Robin There are others OOTB Broadcast Random Consistent Hashing (used by Cluster) Smallest Mailbox More

Pools and Groups Pools are more anonymous Groups are pre-created

Page 32: Creating scalable message driven solutions akkadotnet

FINDING CHILDREN Within an actor, call Context.Child with the name of the child actor

If not found, ActorRefs.Nobody is returned

If found, you have an IActorRef to work with Using ActorSelection doesn’t guarantee actor is initialized

Page 33: Creating scalable message driven solutions akkadotnet

MORE COMPLEX ACTOR DEMO

baseball

gameCoordinator

gameInfo-x

gameInfo-y

playerSupervisor

batter-abatter-bbatter-c

c-01 c-11 c-32

Page 34: Creating scalable message driven solutions akkadotnet

INTEGRATION Integration with other systems is simple

Best to encapsulate in its own actor

Contain any errors there Prevent affecting parts of the system further upstream

Page 35: Creating scalable message driven solutions akkadotnet

ASYNC Actors have messages delivered to them in order via a Mailbox As message is received, handed to Actor to process Messages in mailbox queue up As a result, async processing of messages isn’t possible Receive<> (async msg => { … }) doesn’t work

If you need to perform async tasks within Receive PipeTo(Self) usually does the trick Re-queues message back on Mailbox When delivered, actor resumes

Actor

Mai

lbox

Msg

PipeTo

Page 36: Creating scalable message driven solutions akkadotnet

ACTORS ACROSS PROCESSES Akka.Remote module

Configure via HOCON Human Optimized Configuration Object Notation

Allows an actor system to distribute messages to actors across processes

Location transparency!!

Page 37: Creating scalable message driven solutions akkadotnet

ACTORS ACROSS PROCESSES

baseball

gameCoordinator

gameInfo-x

gameInfo-y

playerSupervisor

batter-abatter-bbatter-c

eventSupervisor

batter-a batter-b

c-01 c-11 c-32

atBatWriter Remotely call actor across process

Page 38: Creating scalable message driven solutions akkadotnet

ACTORS ACROSS PROCESSES Actor Path modified akka.tcp://localhost:50000@{system}/user/{supervisor}/{name}

Protocol and location added to actor path

Protocol defaults to tcp, but you can provide your own

Actor path above is remote path

Page 39: Creating scalable message driven solutions akkadotnet

AKKA.REMOTE DEMO

Page 40: Creating scalable message driven solutions akkadotnet

ELASTICITY WITH ACTORS Akka.Cluster

Multiple nodes of an actor system acting as one

Allows for failure

Can also expand out for performance

Page 41: Creating scalable message driven solutions akkadotnet

SAVING ACTOR STATE Akka.Persistence

Persist each message (or snapshots) to storage

Like event sourcing

Rehydrate actor state after failure or for whatever reason

Page 42: Creating scalable message driven solutions akkadotnet

ASKING AN ACTOR Wait for a response from an actor

Somewhat of an anti-pattern for Actor Model

If used, use sparingly

Page 43: Creating scalable message driven solutions akkadotnet

HANDLING ERRORS An exception during processing with a classic app could crash the whole system

An exception within a child actor is isolated

Page 44: Creating scalable message driven solutions akkadotnet

IS AKKA.NET…? Pub/Sub? No, but it could be

Message Bus, like RabbitMQ or MassTransit Uses messages to communicate Message bus concerned with building a distributed system topology

Storm, ETL/ELT, etc.? Kind of Can build system like that with Akka.NET

Page 45: Creating scalable message driven solutions akkadotnet

RESOURCES http://getakka.net

Petabridge bloghttps://petabridge.com/blog/

Gitter https://gitter.im/akkadotnet/akka.nethttps://gitter.im/petabridge/akka-bootcamp