Advanced akka features

Post on 16-Apr-2017

440 views 0 download

Transcript of Advanced akka features

@johanjanssen42#VoxxedBerlin

Advanced Akka featuresMartin Kanters, Info Support

Johan Janssen, Info Support, @johanjanssen42

Content

▪ Introduction

▪ Why Akka?

▪ Local actor

▪ Remote actor

▪ Scheduling

▪ Cluster

▪ Routing

▪ Cluster singleton

▪ Sharding

▪ Persistence

▪ Akka HTTP

▪ Finite State Machines

▪ Conclusion

▪ Questions

Introduction

Why Akka?

Why Akka?

▪ Concurrent

▪ Scalable

▪ Fault tolerant

▪ More natural programming experience when connecting to other systems

▪ Easy to use?

Local actor

Local actor

Actor on JVM 1

Local actor

Coordinator Actor

Hello conference

Local actor

Coordinator Actor

println("Hello conference")

class Worker extends Actor {def receive = {case x =>println(x)

}}

implicit val system = ActorSystem("ExampleActorSystem")

val workerActorRef = system.actorOf(Props[Worker])workerActorRef ! "Hello conference"

Scala

public class AkkaExampleJava8 extends AbstractActor {

public AkkaExample() {

receive(

match(

String.class, System.out::println

).build()

);

}

}

ActorSystem actorSystem = ActorSystem.create();

ActorRef actorRef =

actorSystem.actorOf(Props.create(AkkaExampleJava8.class));

actorRef.tell("test", ActorRef.noSender());

Java 8

Remote actor

Remote actor

Actor on JVM 1

Actor on JVM 2

val workerActorRef = system.actorOf(Props[Worker])workerActorRef ! "Hello conference"

val workerActorRef = context.actorSelection("akka.tcp://ExampleActorSystem@127.0.0.1:9005/user/workerActor")

workerActorRef ! "Hello conference"

akka {actor {provider =

"akka.remote.RemoteActorRefProvider"}remote {enabled-transports =

["akka.remote.netty.tcp"]netty.tcp {hostname = "127.0.0.1"port = 9002

Remote actor

Coordinator actor

Worker actor

StartMessage

Hello conference

Remote actor

Coordinator actor

Worker actor

WorkerMessage

Greetings from the coordinator:

Hello Conference

Remote actor

Coordinator actor

Worker actor

WorkerResponseMessage

Item processed successfully

Shared protocol

Actor on JVM 1

Actor on JVM 2

Messages

CoordinatorActor on

laptop

WorkerActor on

Raspberry PiWorkerMessage

CoordinatorActor on laptop

WorkerActor on

Raspberry Pi

MessageProtocol

SharedMessages

object SharedMessages {case class WorkerResponseMessage(body: String)case class WorkerMessage(body: String)

}

Message used by application

val workerActorRef = context.actorSelection("akka.tcp://ExampleActorSystem@127.0.0.1:9005/user/workerActor")

workerActorRef ! SharedMessages.WorkerMessage("Greetings from the coordinator: " + body)

Scheduling

Scheduling

Actor

Scheduled once after 1 second

Tick

Scheduled every 5 seconds

Tock

Scheduling

▪ Does not work for fixed point in time like 17:00– Use Quartz

Cluster

Cluster

ActorSystemon JVM 1

ActorSystemon JVM 3

ActorSystemon JVM 2

ActorSystemon JVM 4

Seed nodes

▪ Contact points for automatically joining a cluster

akka {

cluster {

seed-nodes = [

"akka.tcp://ClusterNode@127.0.0.1:2551",

"akka.tcp://ClusterNode@127.0.0.1:2552"

]

}

}

Cluster Worker Node

Port 2551

Association failed with [akka.tcp://ClusterSystem@127.0.0.1:2552

Cluster Worker Node

Port 2551

Worker Node

Port 2552

Member Up with IP: 127.0.0.1 and port: 2551Member Up with IP: 127.0.0.1 and port: 2552

Member Up with IP: 127.0.0.1 and port: 2551Member Up with IP: 127.0.0.1 and port: 2552

Cluster Worker Node

Port 2551

Worker Node

Port 2552

Member Up with IP: 127.0.0.1 and port: 2550

Member Up with IP: 127.0.0.1 and port: 2550

CoordinatorNode

Port 2550

Cluster Worker Node

Port 2551

Worker Node

Port 2552

CoordinatorNode

Port 2550

RegisterWorker

RegisterWorker

Cluster Worker Node

Port 2551

Worker Node

Port 2552

CoordinatorNode

Port 2550

Worker registered with IP: 127.0.0.1 and port: 2551Worker registered with IP: 127.0.0.1 and port: 2552

Routing

Routing

Actor on JVM 1

Actor on JVM 3

Actor on JVM 4

Actor on JVM 2

Loadbalancer

akka {actor {provider = "akka.cluster.ClusterActorRefProvider"

deployment {/coordinator/router {router = round-robin-poolnr-of-instances = 10routees.paths = ["/user/emptystringactor"]cluster {enabled = onallow-local-routees = off

}}

}}

}

Routing

CoordinatorActor on

JVM 1

EmptyStringActor on

JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

Routing

CoordinatorActor on

JVM 1

EmptyStringActor on

JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

HashMap[hostname, counter]

Routing

CoordinatorActor on

JVM 1

EmptyStringActor on

JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2

""

Routing

CoordinatorActor on

JVM 1

EmptyStringActor on

JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2

""

Cluster singleton

Cluster singleton

▪ Only one instance of the actor in the cluster

▪ (Re)created on the oldest node

▪ Can be used for instance for scheduling/caching

Cluster singleton

Actor on JVM 1

Other actors on

JVM 3

Other actors on

JVM 4

Singleton actor and

other actors on JVM 2

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

HashMap[hostname, counter]

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2""

HashMap[hostname, counter]

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

EmptyStringActor on

JVM 2Crash

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

""

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

""

HashMap[hostname, counter]

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

""

Cluster singleton

CoordinatorEmptyString

Actor on JVM 3

EmptyStringActor on

JVM 4

""

HashMap[hostname, counter]

Sharding

Sharding

▪ Dividing a set of actors over a cluster

▪ Actors will be divided into groups called shards

▪ It will divide based on a logical identifier

Sharding

Actor on JVM 1

oddShard on

JVM 3

evenShard on

JVM 2

0, 2, 4, 6, 8

1, 3, 5, 7, 9

Sharding method: ShardResolver

def shardResolver(numberOfShards: Int): ExtractShardId = {case i: Int => (i % numberOfShards).toString

}

Sharding method: IdExtractor

def idExtractor: ExtractEntityId = {case i: Int => (i.toString, “New message: “ + i)

}

Actual message

Persistence

Persistence

▪ Store actor information

▪ Recover after crash

▪ Possibility to take snapshots

Example without persistence

Actor

Cobol

Example without persistence

Actor

Cobol

Example without persistence

Cobol

Actor

Example without persistence

Actor

Java Cobol

Example without persistence

CobolJava

ActorCrash

Restart

Example without persistence

Actor

Example without persistence

Actor

Scala

Example without persistence

Scala

Actor

Persistence

PersistentActor

Cobol

Command

Journal

Persistence

Journal

CobolEvent

PersistentActor

Persistence

Journal

ACKPersistentActor

CobolEvent

Persistence

Cobol

Journal

CobolEvent

PersistentActor

Persistence

Cobol

Journal

CobolEvent

PersistentActor

JavaEvent

Persistence

CobolJava

Journal

CobolEvent

PersistentActorCrash

Restart JavaEvent

Persistence

Journal

CobolEvent

PersistentActor

JavaEvent

Persistence

CobolJava

Journal

CobolEvent

PersistentActor

JavaEvent

Scala

Persistence

CobolJavaScala

Journal

CobolEvent

PersistentActor

JavaEvent

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++

C++

Cobol

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++

C++

Cobol

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++ C++

Cobol

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++

JavaC++

Cobol

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++

Crash

Restart

C++

Cobol

Java

Snapshots

JournalPersistentActor

Snapshot store

State until Event C++ C++

Cobol

Java

Snapshots

CobolC++

JournalPersistentActor

Snapshot store

State until Event C++ C++

Cobol

Java

Snapshots

CobolC++Java

JournalPersistentActor

Snapshot store

State until Event C++ C++

Cobol

Java

Snapshots

CobolC++JavaScala

JournalPersistentActor

Snapshot store

State until Event C++ C++

Cobol

Java

Command Query Responsibility Segregation (CQRS)

CQRS in Akka

Journal

CobolEvent

Cobol

PersistentActor

Persistence Query

Akka HTTP

Akka HTTP

Actor on JVM 1

Actor on JVM 2

Finite State Machine

Finite State Machine

▪ State

▪ Event

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Progress, iterationProgress, iteration

Progress, iteration

NoProgressProgress, 2

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Work harder

Iteration: 0

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Good job!

Iteration: 0

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Wrong direction

Iteration: 0

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Use Akka

Iteration: 0

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Good job!

Iteration: 1

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Wrong direction

Iteration: 1

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject

Use Akka

Iteration: 1

Finite State Machines (FSM)

InprogressProject

CrappyProject

NewProject Get another job!

Iteration: 2

Finite State Machines (FSM)

▪ Two types of events– Progress

– NoProgress

▪ All events should be handled!

▪ Integer used to count the number of iterations

▪ After two iterations a message is shown

Conclusion

Conclusion

▪ Akka can be used with Scala or Java

▪ There is even a .NET version of Akka

▪ Akka is really powerful

▪ Akka is quite easy to use

▪ Some features are still experimental

Questions

Martin Kanters and Johan Janssen @johanjanssen42GitHub: https://github.com/johanjanssen/Akka-examples