akka cluster in java - jcconf 2015

63
#JCConf Akka Cluster in Java Jiayun Zhou [email protected]

Upload: jiayun-zhou

Post on 09-Jan-2017

2.582 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Akka Cluster in Java - JCConf 2015

#JCConf

Akka Cluster in Java

Jiayun [email protected]

Page 2: Akka Cluster in Java - JCConf 2015

Introduction

Page 3: Akka Cluster in Java - JCConf 2015

Akka

Page 4: Akka Cluster in Java - JCConf 2015

Concurrent & Distributed

Page 5: Akka Cluster in Java - JCConf 2015

Actor Model

Page 6: Akka Cluster in Java - JCConf 2015

http://blog.shiftehfar.org/?p=431

Page 7: Akka Cluster in Java - JCConf 2015

Scala

Page 8: Akka Cluster in Java - JCConf 2015

Java?

Page 9: Akka Cluster in Java - JCConf 2015

Scala is better

Page 10: Akka Cluster in Java - JCConf 2015

Java

Page 11: Akka Cluster in Java - JCConf 2015
Page 12: Akka Cluster in Java - JCConf 2015

Maven

Page 13: Akka Cluster in Java - JCConf 2015

Basic

Page 14: Akka Cluster in Java - JCConf 2015

pom.xml

<dependencies><dependency>

<groupId>com.typesafe.akka</groupId><artifactId>akka-actor_2.11</artifactId><version>2.4.1</version>

</dependency></dependencies>

<repositories><repository>

<id>typesafe</id><name>Typesafe Repository</name><url>http://repo.typesafe.com/typesafe/releases/</url>

</repository></repositories>

Page 15: Akka Cluster in Java - JCConf 2015

Main.java

public static void main(String[] args) {// akka.Main.main(new String[]{HelloWorld.class.getName()});

ActorSystem system = ActorSystem.create("Hello");ActorRef a =

system.actorOf(Props.create(HelloWorld.class), "helloWorld");}

Page 16: Akka Cluster in Java - JCConf 2015

HelloWorld Actor

public class HelloWorld extends UntypedActor {

@Overridepublic void preStart() {

final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class), "greeter");

greeter.tell(Greeter.Msg.GREET, getSelf());}

@Overridepublic void onReceive(Object msg) {

if (msg == Greeter.Msg.DONE) {getContext().stop(getSelf());

} elseunhandled(msg);

}}

Page 17: Akka Cluster in Java - JCConf 2015

Greeter Actor

public class Greeter extends UntypedActor {

public static enum Msg {GREET, DONE;

}

@Overridepublic void onReceive(Object msg) {

if (msg == Msg.GREET) {System.out.println("Hello World!");getSender().tell(Msg.DONE, getSelf());

} elseunhandled(msg);

}

}

Page 18: Akka Cluster in Java - JCConf 2015

Sending message

• tell() – Fire and forget• ask() – Send and receive

Page 19: Akka Cluster in Java - JCConf 2015

Avoid Ask

• https://www.safaribooksonline.com/library/view/effective-akka/9781449360061/ch02.html#_avoiding_ask

• https://www.safaribooksonline.com/library/view/effective-akka/9781449360061/ch03.html#_tell_don_8217_t_ask

Page 20: Akka Cluster in Java - JCConf 2015

Remoting

Page 21: Akka Cluster in Java - JCConf 2015

pom.xml

<dependency><groupId>com.typesafe.akka</groupId><artifactId>akka-remote_2.11</artifactId><version>2.4.1</version>

</dependency>

Page 22: Akka Cluster in Java - JCConf 2015

Local application.conf

LocalSys {akka {

actor {provider = "akka.remote.RemoteActorRefProvider"

}remote {enabled-transports = ["akka.remote.netty.tcp"]netty.tcp {hostname = "127.0.0.1"port = 2551

}}

}}

Page 23: Akka Cluster in Java - JCConf 2015

Remote application.conf

RemoteSys {akka {

actor {provider = "akka.remote.RemoteActorRefProvider"

}remote {enabled-transports = ["akka.remote.netty.tcp"]netty.tcp {hostname = "127.0.0.1"port = 2552

}}

}}

Page 24: Akka Cluster in Java - JCConf 2015

Local Main

public static void main(String[] args) throws Exception {

ActorSystem _system = ActorSystem.create("LocalNodeApp",ConfigFactory

.load().getConfig("LocalSys"));ActorRef localActor =

_system.actorOf(Props.create(LocalActor.class));localActor.tell("Hello", null);

Thread.sleep(5000);_system.shutdown();

}

Page 25: Akka Cluster in Java - JCConf 2015

Local Actor

ActorRef remoteActor;

@Overridepublic void preStart() {

//Get a reference to the remote actorremoteActor = getContext().actorFor(

"akka.tcp://[email protected]:2552/user/remoteActor");}

@Overridepublic void onReceive(Object message) throws Exception {

Future<Object> future = Patterns.ask(remoteActor, message.toString(),

timeout);String result = (String) Await.result(future,

timeout.duration());log.info("Message received from Server -> {}", result);

}

Page 26: Akka Cluster in Java - JCConf 2015

Actor Path

akka.<protocol>://<actorsystemname>@<hostname>:<port>/<actor path>

• http://doc.akka.io/docs/akka/2.4.1/general/addressing.html

Page 27: Akka Cluster in Java - JCConf 2015

Remote Main

public static void main(String[] args) {

final ActorSystem system = ActorSystem.create("RemoteNodeApp", ConfigFactory

.load().getConfig("RemoteSys"));

system.actorOf(Props.create(RemoteActor.class), "remoteActor");

Runtime.getRuntime().addShutdownHook(new Thread() {

@Overridepublic void run() {

system.shutdown();}

});}

Page 28: Akka Cluster in Java - JCConf 2015

Remote Actor

@Overridepublic void onReceive(Object message) throws Exception {

if (message instanceof String) {// Get reference to the message sender and

reply backlog.info("Message received -> {}", message);getSender().tell(message + " got something",

null);}

}

Page 29: Akka Cluster in Java - JCConf 2015

Router

Page 30: Akka Cluster in Java - JCConf 2015

Router Mainpublic static void main(String[] args) throws InterruptedException {

ActorSystem _system = ActorSystem.create("RemoteRouteeRouterExample", ConfigFactory.load().getConfig("MyRouterExample"));

Address[] addresses = new Address[]{new Address("akka.tcp", "RemoteNodeApp",

"10.211.55.6", 2552),new Address("akka.tcp", "RemoteNodeApp",

"10.211.55.5", 2552)};

ActorRef router = _system.actorOf(new RemoteRouterConfig(new RoundRobinPool(5), addresses).props(

Props.create(RemoteActor.class)));

for (int i = 1; i <= 10; i++) {// sends randomly to actorsrouter.tell("Hello " + Integer.toString(i), null);

}_system.shutdown();

}

Page 31: Akka Cluster in Java - JCConf 2015

Cluster

Page 32: Akka Cluster in Java - JCConf 2015

pom.xml

<dependency><groupId>com.typesafe.akka</groupId><artifactId>akka-cluster_2.11</artifactId><version>2.4.1</version>

</dependency>

Page 33: Akka Cluster in Java - JCConf 2015

application.conf

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

}remote {log-remote-lifecycle-events = offnetty.tcp {hostname = "127.0.0.1"port = 0

}}

cluster {seed-nodes = ["akka.tcp://[email protected]:2552","akka.tcp://[email protected]:2552"]

auto-down-unreachable-after = 10s}

}

Page 34: Akka Cluster in Java - JCConf 2015

Seed Nodes

Page 35: Akka Cluster in Java - JCConf 2015

Member States

Page 36: Akka Cluster in Java - JCConf 2015

Backend Mainpublic static void main(String[] args) {

// Override the configuration of the port when specified as program argument

final String hostname = args.length > 0 ? args[0] : "127.0.0.1";final String port = args.length > 1 ? args[1] : "0";

final Config config = ConfigFactory.parseString("akka.remote.netty.tcp.hostname=" + hostname).

withFallback(ConfigFactory.parseString("akka.remote.netty.tcp.port=" + port)).

withFallback(ConfigFactory.parseString("akka.cluster.roles = [backend]")).

withFallback(ConfigFactory.load());

ActorSystem system = ActorSystem.create("ClusterSystem", config);

system.actorOf(Props.create(TransformationBackend.class), "backend");

}

Page 37: Akka Cluster in Java - JCConf 2015

Backend Actor - 1

Cluster cluster = Cluster.get(getContext().system());

//subscribe to cluster changes, MemberUp@Overridepublic void preStart() {cluster.subscribe(getSelf(), MemberUp.class);

}

//re-subscribe when restart@Overridepublic void postStop() {cluster.unsubscribe(getSelf());

}

void register(Member member) {if (member.hasRole("frontend"))getContext().actorSelection(member.address() +

"/user/frontend").tell(BACKEND_REGISTRATION, getSelf());

}

Page 38: Akka Cluster in Java - JCConf 2015

Backend Actor - 2@Overridepublic void onReceive(Object message) {

if (message instanceof TransformationJob) {TransformationJob job = (TransformationJob) message;getSender().tell(new

TransformationResult(job.getText().toUpperCase()),getSelf());

} else if (message instanceof CurrentClusterState) {CurrentClusterState state = (CurrentClusterState) message;for (Member member : state.getMembers()) {if (member.status().equals(MemberStatus.up())) {

register(member);}

}

} else if (message instanceof MemberUp) {MemberUp mUp = (MemberUp) message;register(mUp.member());

} else {unhandled(message);

}}

Page 39: Akka Cluster in Java - JCConf 2015

Frontend Main - 1

final String hostname = args.length > 0 ? args[0] : "127.0.0.1";final String port = args.length > 1 ? args[1] : "0";

final Config config = ConfigFactory.parseString("akka.remote.netty.tcp.hostname=" + hostname).

withFallback(ConfigFactory.parseString("akka.remote.netty.tcp.port=" + port)).

withFallback(ConfigFactory.parseString("akka.cluster.roles = [frontend]")).

withFallback(ConfigFactory.load());

ActorSystem system = ActorSystem.create("ClusterSystem", config);

Page 40: Akka Cluster in Java - JCConf 2015

Frontend Main - 2

final ActorRef frontend = system.actorOf(Props.create(TransformationFrontend.class),

"frontend");…system.scheduler().schedule(interval, interval, new Runnable() {

public void run() {Patterns.ask(frontend,

new TransformationJob("hello-" + counter.incrementAndGet()),

timeout).onSuccess(new OnSuccess<Object>() {

public void onSuccess(Object result) {System.out.println(result);

}}, ec);

}

}, ec);

Page 41: Akka Cluster in Java - JCConf 2015

Frontend Actor - 1

List<ActorRef> backends = new ArrayList<ActorRef>();int jobCounter = 0;

@Overridepublic void onReceive(Object message) {if ((message instanceof TransformationJob) &&

backends.isEmpty()) {TransformationJob job = (TransformationJob)

message;getSender().tell(

new JobFailed("Service unavailable, try again later", job),

getSender());

Page 42: Akka Cluster in Java - JCConf 2015

Frontend Actor - 2

} else if (message instanceof TransformationJob) {TransformationJob job = (TransformationJob) message;jobCounter++;backends.get(jobCounter % backends.size())

.forward(job, getContext());

} else if (message.equals(BACKEND_REGISTRATION)) {getContext().watch(getSender());backends.add(getSender());

} else if (message instanceof Terminated) {Terminated terminated = (Terminated) message;backends.remove(terminated.getActor());

} else {unhandled(message);

}}

Page 43: Akka Cluster in Java - JCConf 2015

Run

java -cp .:./* sample.cluster.transformation.TransformationBackendMain 10.211.55.5 2552

java -cp .:./* sample.cluster.transformation.TransformationBackendMain 10.211.55.6 2552

java -cp .:./* sample.cluster.transformation.TransformationFrontendMain 10.211.55.2 2552

Page 44: Akka Cluster in Java - JCConf 2015

Best Practices

• At least two seed nodes• Use fixed port if possible

Page 45: Akka Cluster in Java - JCConf 2015

Something not mentioned

• Supervision• Persistence• …

Page 46: Akka Cluster in Java - JCConf 2015

ZooKeeper

Page 47: Akka Cluster in Java - JCConf 2015

3 ZooKeeper Servers

Page 48: Akka Cluster in Java - JCConf 2015

pom.xml

<dependency><groupId>com.sclasen</groupId><artifactId>akka-zk-cluster-seed_2.11</artifactId><version>0.1.2</version>

</dependency>

Page 49: Akka Cluster in Java - JCConf 2015

application.conf

akka {loglevel = "DEBUG"stdout-loglevel = "DEBUG"actor {provider = "akka.cluster.ClusterActorRefProvider"

}remote {log-remote-lifecycle-events = offnetty.tcp {hostname = "127.0.0.1"port = 0

}}

cluster {// seed-nodes = [// "akka.tcp://[email protected]:2552",// "akka.tcp://[email protected]:2552"]

auto-down-unreachable-after = 10s}

}

Page 50: Akka Cluster in Java - JCConf 2015

reference.conf

akka.cluster.seed.zookeeper {url = "10.211.55.2:2181,10.211.55.5:2181,10.211.55.6:2181"path = "/akka/cluster/seed"

}

Page 51: Akka Cluster in Java - JCConf 2015

Join Cluster

ActorSystem system = ActorSystem.create("ClusterSystem", config);new ZookeeperClusterSeed((ExtendedActorSystem)system).join();

Page 52: Akka Cluster in Java - JCConf 2015

Cluster & Router

Page 53: Akka Cluster in Java - JCConf 2015

factorial.conf - 1

include "application"

# //#min-nr-of-membersakka.cluster.min-nr-of-members = 3# //#min-nr-of-members

# //#role-min-nr-of-membersakka.cluster.role {frontend.min-nr-of-members = 1backend.min-nr-of-members = 2

}# //#role-min-nr-of-members

Page 54: Akka Cluster in Java - JCConf 2015

factorial.conf - 2

# //#adaptive-routerakka.actor.deployment {/factorialFrontend/factorialBackendRouter = {

router = adaptive-group# metrics-selector = heap# metrics-selector = load# metrics-selector = cpumetrics-selector = mixnr-of-instances = 100routees.paths = ["/user/factorialBackend"]cluster {enabled = onuse-role = backendallow-local-routees = off

}}

}# //#adaptive-router

Page 55: Akka Cluster in Java - JCConf 2015

Backend Main

final String port = args.length > 0 ? args[0] : "0";final Config config = ConfigFactory.parseString("akka.remote.netty.tcp.port=" + port).

withFallback(ConfigFactory.parseString("akka.cluster.roles= [backend]")).

withFallback(ConfigFactory.load("factorial"));

ActorSystem system = ActorSystem.create("ClusterSystem", config);new ZookeeperClusterSeed((ExtendedActorSystem)system).join();

system.actorOf(Props.create(FactorialBackend.class), "factorialBackend");

system.actorOf(Props.create(MetricsListener.class), "metricsListener");

Page 56: Akka Cluster in Java - JCConf 2015

Backend Actor

Page 57: Akka Cluster in Java - JCConf 2015

Frontend Main

final int upToN = 200;

final Config config = ConfigFactory.parseString("akka.cluster.roles = [frontend]").withFallback(ConfigFactory.load("factorial"));

final ActorSystem system = ActorSystem.create("ClusterSystem", config);new ZookeeperClusterSeed((ExtendedActorSystem)system).join();

Cluster.get(system).registerOnMemberUp(new Runnable() {@Overridepublic void run() {

system.actorOf(Props.create(FactorialFrontend.class, upToN, true),

"factorialFrontend");}

});

Page 58: Akka Cluster in Java - JCConf 2015

Frontend Actor

ActorRef backend = getContext().actorOf(FromConfig.getInstance().props(),

"factorialBackendRouter");

void sendJobs() {log.info("Starting batch of factorials up to

[{}]", upToN);for (int n = 1; n <= upToN; n++) {

backend.tell(n, getSelf());}

}

Page 59: Akka Cluster in Java - JCConf 2015

Resources

Page 60: Akka Cluster in Java - JCConf 2015

Java Sample Code

Page 61: Akka Cluster in Java - JCConf 2015

https://github.com/jiayun/akka_samples

Page 62: Akka Cluster in Java - JCConf 2015

https://www.safaribooksonline.com/search/?query=Akka&

highlight=true

Page 63: Akka Cluster in Java - JCConf 2015

Thanks