!act,rem,clu #3549 Simplify and enhance routers

* Separate routing logic, to be usable stand alone, e.g. in actors
* Simplify RouterConfig, only a factory
* Move reading of config from Deployer to the RouterConfig
* Distiction between Pool and Group router types
* Remove usage of actorFor, use ActorSelection
* Management messages to add and remove routees
* Simplify the internals of RoutedActorCell & co
* Move resize specific code to separate RoutedActorCell subclass
* Change resizer api to only return capacity change
* Resizer only allowed together with Pool
* Re-implement all routers, and keep old api during deprecation phase
* Replace ClusterRouterConfig, deprecation
* Rewrite documentation
* Migration guide
* Also includes related ticket:
  +act #3087 Create nicer Props factories for RouterConfig
This commit is contained in:
Patrik Nordwall 2013-09-19 08:00:05 +02:00
parent 81ca6fe8c8
commit ebadd567b2
104 changed files with 9671 additions and 5006 deletions

View file

@ -119,8 +119,9 @@ public class ConsistentHashingRouterDocTest {
}
};
ActorRef cache = system.actorOf(Props.create(Cache.class).withRouter(
new ConsistentHashingRouter(10).withHashMapper(hashMapper)),
ActorRef cache = system.actorOf(
new ConsistentHashingRouter(10).withHashMapper(hashMapper).props(
Props.create(Cache.class)),
"cache");
cache.tell(new ConsistentHashableEnvelope(

View file

@ -3,201 +3,164 @@
*/
package docs.jrouting;
import static akka.pattern.Patterns.ask;
import static docs.jrouting.CustomRouterDocTest.Message.DemocratCountResult;
import static docs.jrouting.CustomRouterDocTest.Message.DemocratVote;
import static docs.jrouting.CustomRouterDocTest.Message.RepublicanCountResult;
import static docs.jrouting.CustomRouterDocTest.Message.RepublicanVote;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import akka.routing.FromConfig;
import akka.routing.RoundRobinRoutingLogic;
import akka.routing.Routee;
import akka.routing.RoutingLogic;
import akka.routing.SeveralRoutees;
import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.*;
import scala.concurrent.Await;
import scala.concurrent.Future;
import scala.concurrent.duration.Duration;
import org.junit.ClassRule;
import org.junit.Test;
import static org.junit.Assert.*;
import com.typesafe.config.ConfigFactory;
import scala.collection.immutable.IndexedSeq;
import static akka.japi.Util.immutableIndexedSeq;
import docs.jrouting.RouterDocTest.Parent;
import docs.jrouting.RouterDocTest.Workers;
import docs.routing.CustomRouterDocSpec;
import akka.testkit.JavaTestKit;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.OneForOneStrategy;
import akka.actor.Props;
import akka.actor.SupervisorStrategy;
//#imports1
import akka.actor.UntypedActor;
import akka.dispatch.Dispatchers;
import akka.routing.CustomRoute;
import akka.routing.CustomRouterConfig;
import akka.routing.Destination;
import akka.routing.RoundRobinRouter;
import akka.routing.RouteeProvider;
import akka.testkit.AkkaSpec;
import akka.util.Timeout;
import com.typesafe.config.ConfigFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
//#imports1
public class CustomRouterDocTest {
@ClassRule
public static AkkaJUnitActorSystemResource actorSystemResource =
new AkkaJUnitActorSystemResource(
"CustomRouterDocTest", ConfigFactory.load(ConfigFactory.parseString(
"head{}\nworkers{}").withFallback(AkkaSpec.testConf())));
new AkkaJUnitActorSystemResource("CustomRouterDocTest",
ConfigFactory.parseString(CustomRouterDocSpec.jconfig()));
private final ActorSystem system = actorSystemResource.getSystem();
public static class MyActor extends UntypedActor {
@Override public void onReceive(Object o) {}
}
@Test
public void demonstrateDispatchers() {
//#dispatchers
final ActorRef router = system.actorOf(Props.create(MyActor.class)
// head router will run on "head" dispatcher
.withRouter(new RoundRobinRouter(5).withDispatcher("head"))
// MyActor workers will run on "workers" dispatcher
.withDispatcher("workers"));
//#dispatchers
}
@Test
public void demonstrateSupervisor() {
//#supervision
final SupervisorStrategy strategy =
new OneForOneStrategy(5, Duration.create("1 minute"),
Collections.<Class<? extends Throwable>>singletonList(Exception.class));
final ActorRef router = system.actorOf(Props.create(MyActor.class)
.withRouter(new RoundRobinRouter(5).withSupervisorStrategy(strategy)));
//#supervision
}
//#crTest
@Test
public void countVotesAsIntendedNotAsInFlorida() throws Exception {
ActorRef routedActor = system.actorOf(
Props.empty().withRouter(new VoteCountRouter()));
routedActor.tell(DemocratVote, ActorRef.noSender());
routedActor.tell(DemocratVote, ActorRef.noSender());
routedActor.tell(RepublicanVote, ActorRef.noSender());
routedActor.tell(DemocratVote, ActorRef.noSender());
routedActor.tell(RepublicanVote, ActorRef.noSender());
Timeout timeout = new Timeout(Duration.create(1, "seconds"));
Future<Object> democratsResult =
ask(routedActor, DemocratCountResult, timeout);
Future<Object> republicansResult =
ask(routedActor, RepublicanCountResult, timeout);
assertEquals(3, Await.result(democratsResult, timeout.duration()));
assertEquals(2, Await.result(republicansResult, timeout.duration()));
}
//#crTest
//#CustomRouter
//#crMessages
enum Message {
DemocratVote, DemocratCountResult, RepublicanVote, RepublicanCountResult
}
//#crMessages
//#CustomRouter
static
//#CustomRouter
//#crActors
public class DemocratActor extends UntypedActor {
int counter = 0;
public void onReceive(Object msg) {
switch ((Message) msg) {
case DemocratVote:
counter++;
break;
case DemocratCountResult:
getSender().tell(counter, getSelf());
break;
default:
unhandled(msg);
}
}
}
//#crActors
//#CustomRouter
static
//#CustomRouter
//#crActors
public class RepublicanActor extends UntypedActor {
int counter = 0;
public void onReceive(Object msg) {
switch ((Message) msg) {
case RepublicanVote:
counter++;
break;
case RepublicanCountResult:
getSender().tell(counter, getSelf());
break;
default:
unhandled(msg);
}
}
}
//#crActors
//#CustomRouter
static
//#CustomRouter
//#crRouter
public class VoteCountRouter extends CustomRouterConfig {
//#routing-logic
public class RedundancyRoutingLogic implements RoutingLogic {
private final int nbrCopies;
@Override public String routerDispatcher() {
return Dispatchers.DefaultDispatcherId();
public RedundancyRoutingLogic(int nbrCopies) {
this.nbrCopies = nbrCopies;
}
RoundRobinRoutingLogic roundRobin = new RoundRobinRoutingLogic();
@Override public SupervisorStrategy supervisorStrategy() {
return SupervisorStrategy.defaultStrategy();
}
//#crRoute
@Override
public CustomRoute createCustomRoute(RouteeProvider routeeProvider) {
final ActorRef democratActor =
routeeProvider.context().actorOf(Props.create(DemocratActor.class), "d");
final ActorRef republicanActor =
routeeProvider.context().actorOf(Props.create(RepublicanActor.class), "r");
List<ActorRef> routees =
Arrays.asList(new ActorRef[] { democratActor, republicanActor });
//#crRegisterRoutees
routeeProvider.registerRoutees(routees);
//#crRegisterRoutees
//#crRoutingLogic
return new CustomRoute() {
@Override
public scala.collection.immutable.Seq<Destination> destinationsFor(
ActorRef sender, Object msg) {
switch ((Message) msg) {
case DemocratVote:
case DemocratCountResult:
return akka.japi.Util.immutableSingletonSeq(
new Destination(sender, democratActor));
case RepublicanVote:
case RepublicanCountResult:
return akka.japi.Util.immutableSingletonSeq(
new Destination(sender, republicanActor));
default:
throw new IllegalArgumentException("Unknown message: " + msg);
}
}
};
//#crRoutingLogic
public Routee select(Object message, IndexedSeq<Routee> routees) {
List<Routee> targets = new ArrayList<Routee>();
for (int i = 0; i < nbrCopies; i++) {
targets.add(roundRobin.select(message, routees));
}
return new SeveralRoutees(targets);
}
//#crRoute
}
//#routing-logic
static
//#unit-test-logic
public final class TestRoutee implements Routee {
public final int n;
public TestRoutee(int n) {
this.n = n;
}
@Override
public void send(Object message, ActorRef sender) {
}
@Override
public int hashCode() {
return n;
}
@Override
public boolean equals(Object obj) {
return (obj instanceof TestRoutee) &&
n == ((TestRoutee) obj).n;
}
}
//#unit-test-logic
static public class Storage extends UntypedActor {
public void onReceive(Object msg) {
getSender().tell(msg, getSelf());
}
}
@Test
public void unitTestRoutingLogic() {
//#unit-test-logic
RedundancyRoutingLogic logic = new RedundancyRoutingLogic(3);
List<Routee> routeeList = new ArrayList<Routee>();
for (int n = 1; n <= 7; n++) {
routeeList.add(new TestRoutee(n));
}
IndexedSeq<Routee> routees = immutableIndexedSeq(routeeList);
SeveralRoutees r1 = (SeveralRoutees) logic.select("msg", routees);
assertEquals(r1.getRoutees().get(0), routeeList.get(0));
assertEquals(r1.getRoutees().get(1), routeeList.get(1));
assertEquals(r1.getRoutees().get(2), routeeList.get(2));
SeveralRoutees r2 = (SeveralRoutees) logic.select("msg", routees);
assertEquals(r2.getRoutees().get(0), routeeList.get(3));
assertEquals(r2.getRoutees().get(1), routeeList.get(4));
assertEquals(r2.getRoutees().get(2), routeeList.get(5));
SeveralRoutees r3 = (SeveralRoutees) logic.select("msg", routees);
assertEquals(r3.getRoutees().get(0), routeeList.get(6));
assertEquals(r3.getRoutees().get(1), routeeList.get(0));
assertEquals(r3.getRoutees().get(2), routeeList.get(1));
//#unit-test-logic
}
@Test
public void demonstrateUsageOfCustomRouter() {
new JavaTestKit(system) {{
//#usage-1
for (int n = 1; n <= 10; n++) {
system.actorOf(Props.create(Storage.class), "s" + n);
}
List<String> paths = new ArrayList<String>();
for (int n = 1; n <= 10; n++) {
paths.add("/user/s" + n);
}
ActorRef redundancy1 =
system.actorOf(new RedundancyGroup(paths, 3).props(),
"redundancy1");
redundancy1.tell("important", getTestActor());
//#usage-1
for (int i = 0; i < 3; i++) {
expectMsgEquals("important");
}
//#usage-2
ActorRef redundancy2 = system.actorOf(FromConfig.getInstance().props(),
"redundancy2");
redundancy2.tell("very important", getTestActor());
//#usage-2
for (int i = 0; i < 5; i++) {
expectMsgEquals("very important");
}
}};
}
//#crRouter
//#CustomRouter
}

View file

@ -1,48 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import java.io.Serializable;
import akka.actor.UntypedActor;
//#fibonacciActor
public class FibonacciActor extends UntypedActor {
public void onReceive(Object msg) {
if (msg instanceof FibonacciNumber) {
FibonacciNumber fibonacciNumber = (FibonacciNumber) msg;
getSender().tell(fibonacci(fibonacciNumber.getNbr()), getSelf());
} else {
unhandled(msg);
}
}
private int fibonacci(int n) {
return fib(n, 1, 0);
}
private int fib(int n, int b, int a) {
if (n == 0)
return a;
// recursion
return fib(n - 1, a + b, b);
}
public static class FibonacciNumber implements Serializable {
private static final long serialVersionUID = 1L;
private final int nbr;
public FibonacciNumber(int nbr) {
this.nbr = nbr;
}
public int getNbr() {
return nbr;
}
}
}
//#fibonacciActor

View file

@ -1,75 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import akka.routing.ScatterGatherFirstCompletedRouter;
import akka.routing.BroadcastRouter;
import akka.routing.RandomRouter;
import akka.routing.RoundRobinRouter;
import akka.routing.SmallestMailboxRouter;
import akka.actor.UntypedActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import scala.concurrent.Future;
import scala.concurrent.Await;
//#parentActor
public class ParentActor extends UntypedActor {
public void onReceive(Object msg) throws Exception {
if (msg.equals("rrr")) {
//#roundRobinRouter
ActorRef roundRobinRouter = getContext().actorOf(
Props.create(PrintlnActor.class).withRouter(new RoundRobinRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
roundRobinRouter.tell(i, getSelf());
}
//#roundRobinRouter
} else if (msg.equals("rr")) {
//#randomRouter
ActorRef randomRouter = getContext().actorOf(
Props.create(PrintlnActor.class).withRouter(new RandomRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
randomRouter.tell(i, getSelf());
}
//#randomRouter
} else if (msg.equals("smr")) {
//#smallestMailboxRouter
ActorRef smallestMailboxRouter = getContext().actorOf(
Props.create(PrintlnActor.class).withRouter(new SmallestMailboxRouter(5)),
"router");
for (int i = 1; i <= 10; i++) {
smallestMailboxRouter.tell(i, getSelf());
}
//#smallestMailboxRouter
} else if (msg.equals("br")) {
//#broadcastRouter
ActorRef broadcastRouter = getContext().actorOf(
Props.create(PrintlnActor.class).withRouter(new BroadcastRouter(5)), "router");
broadcastRouter.tell("this is a broadcast message", getSelf());
//#broadcastRouter
} else if (msg.equals("sgfcr")) {
//#scatterGatherFirstCompletedRouter
ActorRef scatterGatherFirstCompletedRouter = getContext().actorOf(
Props.create(FibonacciActor.class).withRouter(
new ScatterGatherFirstCompletedRouter(5, Duration.create(2, "seconds"))),
"router");
Timeout timeout = new Timeout(Duration.create(5, "seconds"));
Future<Object> futureResult = akka.pattern.Patterns.ask(
scatterGatherFirstCompletedRouter, new FibonacciActor.FibonacciNumber(10),
timeout);
int result = (Integer) Await.result(futureResult, timeout.duration());
//#scatterGatherFirstCompletedRouter
System.out.println(
String.format("The result of calculating Fibonacci for 10 is %d", result));
} else {
unhandled(msg);
}
}
}
//#parentActor

View file

@ -1,16 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import akka.actor.UntypedActor;
//#printlnActor
public class PrintlnActor extends UntypedActor {
public void onReceive(Object msg) {
System.out.println(String.format("Received message '%s' in actor %s",
msg, getSelf().path().name()));
}
}
//#printlnActor

View file

@ -0,0 +1,58 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
//#group
import java.util.List;
import scala.Option;
import scala.collection.immutable.Iterable;
import akka.actor.ActorContext;
import akka.actor.ActorPath;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.dispatch.Dispatchers;
import akka.routing.Group;
import akka.routing.Routee;
import akka.routing.Router;
import akka.routing.RouterActor;
import akka.routing.RouterConfig;
import akka.routing.RoutingLogic;
import com.typesafe.config.Config;
import akka.routing.GroupBase;
import static docs.jrouting.CustomRouterDocTest.RedundancyRoutingLogic;
public class RedundancyGroup extends GroupBase {
private final List<String> paths;
private final int nbrCopies;
public RedundancyGroup(List<String> paths, int nbrCopies) {
this.paths = paths;
this.nbrCopies = nbrCopies;
}
public RedundancyGroup(Config config) {
this(config.getStringList("routees.paths"),
config.getInt("nbr-copies"));
}
@Override
public java.lang.Iterable<String> getPaths() {
return paths;
}
@Override
public Router createRouter(ActorSystem system) {
return new Router(new RedundancyRoutingLogic(nbrCopies));
}
@Override
public String routerDispatcher() {
return Dispatchers.DefaultDispatcherId();
}
}
//#group

View file

@ -0,0 +1,412 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.ClassRule;
import org.junit.Test;
import static org.junit.Assert.*;
import scala.concurrent.duration.Duration;
import scala.concurrent.duration.FiniteDuration;
import com.typesafe.config.ConfigFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import akka.testkit.JavaTestKit;
import akka.actor.ActorSystem;
//#imports1
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.actor.UntypedActor;
import akka.routing.ActorRefRoutee;
import akka.routing.Routee;
import akka.routing.Router;
//#imports1
//#imports2
import akka.actor.Address;
import akka.actor.AddressFromURIString;
import akka.actor.Kill;
import akka.actor.PoisonPill;
import akka.actor.SupervisorStrategy;
import akka.actor.OneForOneStrategy;
import akka.remote.routing.RemoteRouterConfig;
import akka.routing.Broadcast;
import akka.routing.BroadcastGroup;
import akka.routing.BroadcastPool;
import akka.routing.ConsistentHashingGroup;
import akka.routing.ConsistentHashingPool;
import akka.routing.DefaultResizer;
import akka.routing.FromConfig;
import akka.routing.RandomGroup;
import akka.routing.RandomPool;
import akka.routing.RoundRobinGroup;
import akka.routing.RoundRobinPool;
import akka.routing.RoundRobinRoutingLogic;
import akka.routing.ScatterGatherFirstCompletedGroup;
import akka.routing.ScatterGatherFirstCompletedPool;
import akka.routing.SmallestMailboxPool;
//#imports2
public class RouterDocTest {
@ClassRule
public static AkkaJUnitActorSystemResource actorSystemResource =
new AkkaJUnitActorSystemResource("RouterDocTest",
ConfigFactory.parseString(docs.routing.RouterDocSpec.config()));
private final ActorSystem system = actorSystemResource.getSystem();
static
//#router-in-actor
public final class Work implements Serializable {
private static final long serialVersionUID = 1L;
public final String payload;
public Work(String payload) {
this.payload = payload;
}
}
//#router-in-actor
static
//#router-in-actor
public class Master extends UntypedActor {
Router router;
{
List<Routee> routees = new ArrayList<Routee>();
for (int i = 0; i < 5; i++) {
ActorRef r = getContext().actorOf(Props.create(Worker.class));
getContext().watch(r);
routees.add(new ActorRefRoutee(r));
}
router = new Router(new RoundRobinRoutingLogic(), routees);
}
public void onReceive(Object msg) {
if (msg instanceof Work) {
router.route(msg, getSender());
} else if (msg instanceof Terminated) {
router = router.removeRoutee(((Terminated) msg).actor());
ActorRef r = getContext().actorOf(Props.create(Worker.class));
getContext().watch(r);
router = router.addRoutee(new ActorRefRoutee(r));
}
}
}
//#router-in-actor
static public class Worker extends UntypedActor {
public void onReceive(Object msg) {}
}
static public class Echo extends UntypedActor {
public void onReceive(Object msg) {
getSender().tell(msg, getSelf());
}
}
static public class Replier extends UntypedActor {
public void onReceive(Object msg) {
//#reply-with-self
getSender().tell("reply", getSelf());
//#reply-with-self
//#reply-with-parent
getSender().tell("reply", getContext().parent());
//#reply-with-parent
}
}
static
//#create-worker-actors
public class Workers extends UntypedActor {
@Override public void preStart() {
getContext().actorOf(Props.create(Worker.class), "w1");
getContext().actorOf(Props.create(Worker.class), "w2");
getContext().actorOf(Props.create(Worker.class), "w3");
}
// ...
//#create-worker-actors
public void onReceive(Object msg) {}
}
static public class Parent extends UntypedActor {
//#paths
List<String> paths = Arrays.asList("/user/workers/w1", "/user/workers/w2",
"/user/workers/w3");
//#paths
//#round-robin-pool-1
ActorRef router1 =
getContext().actorOf(FromConfig.getInstance().props(Props.create(Worker.class)),
"router1");
//#round-robin-pool-1
//#round-robin-pool-2
ActorRef router2 =
getContext().actorOf(new RoundRobinPool(5).props(Props.create(Worker.class)),
"router2");
//#round-robin-pool-2
//#round-robin-group-1
ActorRef router3 =
getContext().actorOf(FromConfig.getInstance().props(), "router3");
//#round-robin-group-1
//#round-robin-group-2
ActorRef router4 =
getContext().actorOf(new RoundRobinGroup(paths).props(), "router4");
//#round-robin-group-2
//#random-pool-1
ActorRef router5 =
getContext().actorOf(FromConfig.getInstance().props(
Props.create(Worker.class)), "router5");
//#random-pool-1
//#random-pool-2
ActorRef router6 =
getContext().actorOf(new RandomPool(5).props(Props.create(Worker.class)),
"router6");
//#random-pool-2
//#random-group-1
ActorRef router7 =
getContext().actorOf(FromConfig.getInstance().props(), "router7");
//#random-group-1
//#random-group-2
ActorRef router8 =
getContext().actorOf(new RandomGroup(paths).props(), "router8");
//#random-group-2
//#smallest-mailbox-pool-1
ActorRef router9 =
getContext().actorOf(FromConfig.getInstance().props(
Props.create(Worker.class)), "router9");
//#smallest-mailbox-pool-1
//#smallest-mailbox-pool-2
ActorRef router10 =
getContext().actorOf(new SmallestMailboxPool(5).props(
Props.create(Worker.class)), "router10");
//#smallest-mailbox-pool-2
//#broadcast-pool-1
ActorRef router11 =
getContext().actorOf(FromConfig.getInstance().props(
Props.create(Worker.class)), "router11");
//#broadcast-pool-1
//#broadcast-pool-2
ActorRef router12 =
getContext().actorOf(new BroadcastPool(5).props(Props.create(Worker.class)),
"router12");
//#broadcast-pool-2
//#broadcast-group-1
ActorRef router13 =
getContext().actorOf(FromConfig.getInstance().props(), "router13");
//#broadcast-group-1
//#broadcast-group-2
ActorRef router14 =
getContext().actorOf(new BroadcastGroup(paths).props(), "router14");
//#broadcast-group-2
//#scatter-gather-pool-1
ActorRef router15 =
getContext().actorOf(FromConfig.getInstance().props(
Props.create(Worker.class)), "router15");
//#scatter-gather-pool-1
//#scatter-gather-pool-2
FiniteDuration within = FiniteDuration.create(10, TimeUnit.SECONDS);
ActorRef router16 =
getContext().actorOf(new ScatterGatherFirstCompletedPool(5, within).props(
Props.create(Worker.class)), "router16");
//#scatter-gather-pool-2
//#scatter-gather-group-1
ActorRef router17 =
getContext().actorOf(FromConfig.getInstance().props(), "router17");
//#scatter-gather-group-1
//#scatter-gather-group-2
FiniteDuration within2 = FiniteDuration.create(10, TimeUnit.SECONDS);
ActorRef router18 =
getContext().actorOf(new ScatterGatherFirstCompletedGroup(paths, within2).props(),
"router18");
//#scatter-gather-group-2
//#consistent-hashing-pool-1
ActorRef router19 =
getContext().actorOf(FromConfig.getInstance().props(Props.create(Worker.class)),
"router19");
//#consistent-hashing-pool-1
//#consistent-hashing-pool-2
ActorRef router20 =
getContext().actorOf(new ConsistentHashingPool(5).props(
Props.create(Worker.class)), "router20");
//#consistent-hashing-pool-2
//#consistent-hashing-group-1
ActorRef router21 =
getContext().actorOf(FromConfig.getInstance().props(), "router21");
//#consistent-hashing-group-1
//#consistent-hashing-group-2
ActorRef router22 =
getContext().actorOf(new ConsistentHashingGroup(paths).props(), "router22");
//#consistent-hashing-group-2
//#resize-pool-1
ActorRef router23 =
getContext().actorOf(FromConfig.getInstance().props(
Props.create(Worker.class)), "router23");
//#resize-pool-1
//#resize-pool-2
DefaultResizer resizer = new DefaultResizer(2, 15);
ActorRef router24 =
getContext().actorOf(new RoundRobinPool(5).withResizer(resizer).props(
Props.create(Worker.class)), "router24");
//#resize-pool-2
public void onReceive(Object msg) {}
}
@Test
public void createActors() {
//#create-workers
system.actorOf(Props.create(Workers.class), "workers");
//#create-workers
//#create-parent
system.actorOf(Props.create(Parent.class), "parent");
//#create-parent
}
@Test
public void demonstrateDispatcher() {
//#dispatchers
Props props =
// head will run on "router-dispatcher" dispatcher
new RoundRobinPool(5).withDispatcher("router-dispatcher").props(
Props.create(Worker.class))
// Worker routees will run on "workers-dispatcher" dispatcher
.withDispatcher("workers-dispatcher");
ActorRef router = system.actorOf(props);
//#dispatchers
}
@Test
public void demonstrateBroadcast() {
new JavaTestKit(system) {{
ActorRef router = system.actorOf(new RoundRobinPool(5).props(
Props.create(Echo.class)));
//#broadcastDavyJonesWarning
router.tell(new Broadcast("Watch out for Davy Jones' locker"), getTestActor());
//#broadcastDavyJonesWarning
assertEquals(5, receiveN(5).length);
}};
}
@Test
public void demonstratePoisonPill() {
new JavaTestKit(system) {{
ActorRef router = watch(system.actorOf(new RoundRobinPool(5).props(
Props.create(Echo.class))));
//#poisonPill
router.tell(PoisonPill.getInstance(), getTestActor());
//#poisonPill
expectTerminated(router);
}};
}
@Test
public void demonstrateBroadcastPoisonPill() {
new JavaTestKit(system) {{
ActorRef router = watch(system.actorOf(new RoundRobinPool(5).props(
Props.create(Echo.class))));
//#broadcastPoisonPill
router.tell(new Broadcast(PoisonPill.getInstance()), getTestActor());
//#broadcastPoisonPill
expectTerminated(router);
}};
}
@Test
public void demonstrateKill() {
new JavaTestKit(system) {{
ActorRef router = watch(system.actorOf(new RoundRobinPool(5).props(
Props.create(Echo.class))));
//#kill
router.tell(Kill.getInstance(), getTestActor());
//#kill
expectTerminated(router);
}};
}
@Test
public void demonstrateBroadcastKill() {
new JavaTestKit(system) {{
ActorRef router = watch(system.actorOf(new RoundRobinPool(5).props(
Props.create(Echo.class))));
//#broadcastKill
router.tell(new Broadcast(Kill.getInstance()), getTestActor());
//#broadcastKill
expectTerminated(router);
}};
}
@Test
public void demonstrateRemoteDeploy() {
//#remoteRoutees
Address[] addresses = {
new Address("akka", "remotesys", "otherhost", 1234),
AddressFromURIString.parse("akka://othersys@anotherhost:1234")};
ActorRef routerRemote = system.actorOf(
new RemoteRouterConfig(new RoundRobinPool(5), addresses).props(
Props.create(Echo.class)));
//#remoteRoutees
}
@Test
public void demonstrateSupervisor() {
//#supervision
final SupervisorStrategy strategy =
new OneForOneStrategy(5, Duration.create(1, TimeUnit.MINUTES),
Collections.<Class<? extends Throwable>>singletonList(Exception.class));
final ActorRef router = system.actorOf(new RoundRobinPool(5).
withSupervisorStrategy(strategy).props(Props.create(Echo.class)));
//#supervision
}
}

View file

@ -1,61 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import akka.routing.FromConfig;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.ActorSystem;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.Config;
public class RouterViaConfigExample {
public static class ExampleActor extends UntypedActor {
public void onReceive(Object msg) {
if (msg instanceof Message) {
Message message = (Message) msg;
System.out.println(String.format("Received %s in router %s",
message.getNbr(), getSelf().path().name()));
} else {
unhandled(msg);
}
}
public static class Message {
private final int nbr;
public Message(int nbr) {
this.nbr = nbr;
}
public int getNbr() {
return nbr;
}
}
}
public static void main(String... args) {
Config config = ConfigFactory.parseString("akka.actor.deployment {\n" + " /router {\n"
+ " router = round-robin\n" + " nr-of-instances = 5\n" + " }\n" + "}\n");
ActorSystem system = ActorSystem.create("Example", config);
//#configurableRouting
ActorRef router = system.actorOf(
Props.create(ExampleActor.class).withRouter(new FromConfig()), "myrouter1");
//#configurableRouting
for (int i = 1; i <= 10; i++) {
router.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
//#configurableRoutingWithResizer
ActorRef router2 = system.actorOf(
Props.create(ExampleActor.class).withRouter(new FromConfig()), "myrouter2");
//#configurableRoutingWithResizer
for (int i = 1; i <= 10; i++) {
router2.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
}
}

View file

@ -1,122 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import java.util.Arrays;
import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.ClassRule;
import org.junit.Test;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Kill;
import akka.actor.PoisonPill;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.routing.Broadcast;
import akka.routing.RoundRobinRouter;
import akka.testkit.JavaTestKit;
import docs.jrouting.RouterViaProgramExample.ExampleActor;
import docs.routing.RouterViaProgramDocSpec.Echo;
public class RouterViaProgramDocTest {
@ClassRule
public static AkkaJUnitActorSystemResource actorSystemResource =
new AkkaJUnitActorSystemResource("RouterViaProgramDocTest");
private final ActorSystem system = actorSystemResource.getSystem();
private static class JavaTestKitWithSelf extends JavaTestKit {
public JavaTestKitWithSelf(ActorSystem system) {
super(system);
}
/**
* Wrap `getRef()` so our examples look like they're within a normal actor.
*/
public ActorRef getSelf() {
return getRef();
}
}
@SuppressWarnings("unused")
@Test
public void demonstrateRouteesFromPaths() {
new JavaTestKit(system) {{
//#programmaticRoutingRouteePaths
ActorRef actor1 = system.actorOf(Props.create(ExampleActor.class), "actor1");
ActorRef actor2 = system.actorOf(Props.create(ExampleActor.class), "actor2");
ActorRef actor3 = system.actorOf(Props.create(ExampleActor.class), "actor3");
Iterable<String> routees = Arrays.asList(
new String[] { "/user/actor1", "/user/actor2", "/user/actor3" });
ActorRef router = system.actorOf(
Props.empty().withRouter(new RoundRobinRouter(routees)));
//#programmaticRoutingRouteePaths
for (int i = 1; i <= 6; i++) {
router.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
}};
}
@Test
public void demonstrateBroadcast() {
new JavaTestKitWithSelf(system) {{
ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
//#broadcastDavyJonesWarning
router.tell(new Broadcast("Watch out for Davy Jones' locker"), getSelf());
//#broadcastDavyJonesWarning
receiveN(5, duration("5 seconds"));
}};
}
@Test
public void demonstratePoisonPill() {
new JavaTestKitWithSelf(system) {{
ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#poisonPill
router.tell(PoisonPill.getInstance(), getSelf());
//#poisonPill
expectMsgClass(Terminated.class);
}};
}
@Test
public void demonstrateBroadcastOfPoisonPill() {
new JavaTestKitWithSelf(system) {{
ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#broadcastPoisonPill
router.tell(new Broadcast(PoisonPill.getInstance()), getSelf());
//#broadcastPoisonPill
expectMsgClass(Terminated.class);
}};
}
@Test
public void demonstrateKill() {
new JavaTestKitWithSelf(system) {{
ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#kill
router.tell(Kill.getInstance(), getSelf());
//#kill
expectMsgClass(Terminated.class);
}};
}
@Test
public void demonstrateBroadcastOfKill() {
new JavaTestKitWithSelf(system) {{
ActorRef router = system.actorOf(Props.create(Echo.class).withRouter(new RoundRobinRouter(5)));
watch(router);
//#broadcastKill
router.tell(new Broadcast(Kill.getInstance()), getSelf());
//#broadcastKill
expectMsgClass(Terminated.class);
}};
}
}

View file

@ -1,103 +0,0 @@
/**
* Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.jrouting;
import akka.routing.RoundRobinRouter;
import akka.routing.DefaultResizer;
import akka.remote.routing.RemoteRouterConfig;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.UntypedActor;
import akka.actor.ActorSystem;
import akka.actor.Address;
import akka.actor.AddressFromURIString;
import java.util.Arrays;
public class RouterViaProgramExample {
public static class ExampleActor extends UntypedActor {
public void onReceive(Object msg) {
if (msg instanceof Message) {
Message message = (Message) msg;
System.out.println(String.format("Received %s in router %s",
message.getNbr(), getSelf().path().name()));
} else {
unhandled(msg);
}
}
public static class Message {
private final int nbr;
public Message(int nbr) {
this.nbr = nbr;
}
public int getNbr() {
return nbr;
}
}
}
@SuppressWarnings("unused")
public static void main(String... args) {
ActorSystem system = ActorSystem.create("RPE");
//#programmaticRoutingNrOfInstances
int nrOfInstances = 5;
ActorRef router1 = system.actorOf(
Props.create(ExampleActor.class).withRouter(new RoundRobinRouter(nrOfInstances)));
//#programmaticRoutingNrOfInstances
for (int i = 1; i <= 6; i++) {
router1.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
//#programmaticRoutingRoutees
ActorRef actor1 = system.actorOf(Props.create(ExampleActor.class));
ActorRef actor2 = system.actorOf(Props.create(ExampleActor.class));
ActorRef actor3 = system.actorOf(Props.create(ExampleActor.class));
Iterable<ActorRef> routees = Arrays.asList(
new ActorRef[] { actor1, actor2, actor3 });
ActorRef router2 = system.actorOf(
Props.empty().withRouter(RoundRobinRouter.create(routees)));
//#programmaticRoutingRoutees
for (int i = 1; i <= 6; i++) {
router2.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
//#programmaticRoutingWithResizer
int lowerBound = 2;
int upperBound = 15;
DefaultResizer resizer = new DefaultResizer(lowerBound, upperBound);
ActorRef router3 = system.actorOf(
Props.create(ExampleActor.class).withRouter(new RoundRobinRouter(resizer)));
//#programmaticRoutingWithResizer
for (int i = 1; i <= 6; i++) {
router3.tell(new ExampleActor.Message(i), ActorRef.noSender());
}
//#remoteRoutees
Address addr1 = new Address("akka", "remotesys", "otherhost", 1234);
Address addr2 = AddressFromURIString.parse("akka://othersys@anotherhost:1234");
Address[] addresses = new Address[] { addr1, addr2 };
ActorRef routerRemote = system.actorOf(Props.create(ExampleActor.class)
.withRouter(new RemoteRouterConfig(new RoundRobinRouter(5), addresses)));
//#remoteRoutees
}
@SuppressWarnings("unused")
private class CompileCheckJavaDocsForRouting extends UntypedActor {
@Override
public void onReceive(Object o) {
//#reply-with-parent
getSender().tell("reply", getContext().parent()); // replies go to router
//#reply-with-parent
//#reply-with-self
getSender().tell("reply", getSelf()); // replies go to this actor
//#reply-with-self
}
}
}