95 lines
3.2 KiB
Java
95 lines
3.2 KiB
Java
/*
|
|
* Copyright (C) 2018-2021 Lightbend Inc. <https://www.lightbend.com>
|
|
*/
|
|
|
|
package jdocs.cluster;
|
|
|
|
import akka.cluster.routing.ClusterRouterGroup;
|
|
import akka.cluster.routing.ClusterRouterGroupSettings;
|
|
import akka.cluster.routing.ClusterRouterPool;
|
|
import akka.cluster.routing.ClusterRouterPoolSettings;
|
|
import akka.routing.ConsistentHashingGroup;
|
|
import akka.routing.ConsistentHashingPool;
|
|
import jdocs.cluster.StatsMessages.StatsJob;
|
|
import akka.actor.ActorRef;
|
|
import akka.actor.Props;
|
|
import akka.actor.AbstractActor;
|
|
import akka.routing.ConsistentHashingRouter.ConsistentHashableEnvelope;
|
|
import akka.routing.FromConfig;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
// #service
|
|
public class StatsService extends AbstractActor {
|
|
|
|
// This router is used both with lookup and deploy of routees. If you
|
|
// have a router with only lookup of routees you can use Props.empty()
|
|
// instead of Props.create(StatsWorker.class).
|
|
ActorRef workerRouter =
|
|
getContext()
|
|
.actorOf(FromConfig.getInstance().props(Props.create(StatsWorker.class)), "workerRouter");
|
|
|
|
@Override
|
|
public Receive createReceive() {
|
|
return receiveBuilder()
|
|
.match(
|
|
StatsJob.class,
|
|
job -> !job.getText().isEmpty(),
|
|
job -> {
|
|
String[] words = job.getText().split(" ");
|
|
ActorRef replyTo = getSender();
|
|
|
|
// create actor that collects replies from workers
|
|
ActorRef aggregator =
|
|
getContext().actorOf(Props.create(StatsAggregator.class, words.length, replyTo));
|
|
|
|
// send each word to a worker
|
|
for (String word : words) {
|
|
workerRouter.tell(new ConsistentHashableEnvelope(word, word), aggregator);
|
|
}
|
|
})
|
|
.build();
|
|
}
|
|
}
|
|
// #service
|
|
|
|
// not used, only for documentation
|
|
abstract class StatsService2 extends AbstractActor {
|
|
// #router-lookup-in-code
|
|
int totalInstances = 100;
|
|
Iterable<String> routeesPaths = Collections.singletonList("/user/statsWorker");
|
|
boolean allowLocalRoutees = true;
|
|
Set<String> useRoles = new HashSet<>(Arrays.asList("compute"));
|
|
ActorRef workerRouter =
|
|
getContext()
|
|
.actorOf(
|
|
new ClusterRouterGroup(
|
|
new ConsistentHashingGroup(routeesPaths),
|
|
new ClusterRouterGroupSettings(
|
|
totalInstances, routeesPaths, allowLocalRoutees, useRoles))
|
|
.props(),
|
|
"workerRouter2");
|
|
// #router-lookup-in-code
|
|
}
|
|
|
|
// not used, only for documentation
|
|
abstract class StatsService3 extends AbstractActor {
|
|
// #router-deploy-in-code
|
|
int totalInstances = 100;
|
|
int maxInstancesPerNode = 3;
|
|
boolean allowLocalRoutees = false;
|
|
Set<String> useRoles = new HashSet<>(Arrays.asList("compute"));
|
|
ActorRef workerRouter =
|
|
getContext()
|
|
.actorOf(
|
|
new ClusterRouterPool(
|
|
new ConsistentHashingPool(0),
|
|
new ClusterRouterPoolSettings(
|
|
totalInstances, maxInstancesPerNode, allowLocalRoutees, useRoles))
|
|
.props(Props.create(StatsWorker.class)),
|
|
"workerRouter3");
|
|
// #router-deploy-in-code
|
|
}
|