Merge remote-tracking branch 'origin/master' into wip-1581-patterns-ask
This commit is contained in:
commit
1daaee98aa
141 changed files with 4660 additions and 5579 deletions
|
|
@ -4,6 +4,7 @@
|
|||
package akka.docs.actor;
|
||||
|
||||
//#imports
|
||||
|
||||
import akka.dispatch.*;
|
||||
import akka.actor.*;
|
||||
import akka.japi.*;
|
||||
|
|
@ -103,15 +104,14 @@ public class TypedActorDocTestBase {
|
|||
try {
|
||||
//#typed-actor-create1
|
||||
Squarer mySquarer =
|
||||
TypedActor.get(system).typedActorOf(Squarer.class, SquarerImpl.class, new Props());
|
||||
TypedActor.get(system).typedActorOf(new TypedProps<SquarerImpl>(Squarer.class, SquarerImpl.class));
|
||||
//#typed-actor-create1
|
||||
//#typed-actor-create2
|
||||
Squarer otherSquarer =
|
||||
TypedActor.get(system).typedActorOf(Squarer.class,
|
||||
TypedActor.get(system).typedActorOf(new TypedProps<SquarerImpl>(Squarer.class,
|
||||
new Creator<SquarerImpl>() {
|
||||
public SquarerImpl create() { return new SquarerImpl("foo"); }
|
||||
},
|
||||
new Props(),
|
||||
}),
|
||||
"name");
|
||||
//#typed-actor-create2
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,14 @@ import akka.japi.Procedure;
|
|||
import akka.actor.Terminated;
|
||||
//#import-watch
|
||||
|
||||
//#import-gracefulStop
|
||||
import static akka.pattern.Patterns.gracefulStop;
|
||||
import akka.dispatch.Future;
|
||||
import akka.dispatch.Await;
|
||||
import akka.util.Duration;
|
||||
import akka.actor.ActorTimeoutException;
|
||||
//#import-gracefulStop
|
||||
|
||||
import akka.actor.Props;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.UntypedActorFactory;
|
||||
|
|
@ -59,7 +67,6 @@ public class UntypedActorDocTestBase {
|
|||
return new MyUntypedActor();
|
||||
}
|
||||
});
|
||||
Props props5 = props4.withTimeout(new Timeout(1000));
|
||||
//#creating-props-config
|
||||
}
|
||||
|
||||
|
|
@ -102,8 +109,7 @@ public class UntypedActorDocTestBase {
|
|||
public void propsActorOf() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
//#creating-props
|
||||
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"),
|
||||
"myactor");
|
||||
ActorRef myActor = system.actorOf(new Props(MyUntypedActor.class).withDispatcher("my-dispatcher"), "myactor");
|
||||
//#creating-props
|
||||
myActor.tell("test");
|
||||
system.shutdown();
|
||||
|
|
@ -176,6 +182,23 @@ public class UntypedActorDocTestBase {
|
|||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usePatternsGracefulStop() {
|
||||
ActorSystem system = ActorSystem.create("MySystem");
|
||||
ActorRef actorRef = system.actorOf(new Props(MyUntypedActor.class));
|
||||
//#gracefulStop
|
||||
|
||||
try {
|
||||
Future<Boolean> stopped = gracefulStop(actorRef, Duration.create(5, TimeUnit.SECONDS), system);
|
||||
Await.result(stopped, Duration.create(6, TimeUnit.SECONDS));
|
||||
// the actor has been stopped
|
||||
} catch (ActorTimeoutException e) {
|
||||
// the actor wasn't stopped within 5 seconds
|
||||
}
|
||||
//#gracefulStop
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
public static class MyActor extends UntypedActor {
|
||||
|
||||
public MyActor(String s) {
|
||||
|
|
@ -266,6 +289,7 @@ public class UntypedActorDocTestBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#hot-swap-actor
|
||||
|
||||
//#watch
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package akka.docs.jrouting;
|
||||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class CustomRouterDocTest extends CustomRouterDocTestBase with JUnitSuite
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.docs.jrouting;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import akka.actor.*;
|
||||
import akka.routing.*;
|
||||
import akka.util.Duration;
|
||||
import akka.util.Timeout;
|
||||
import akka.dispatch.Await;
|
||||
import akka.dispatch.Future;
|
||||
import akka.testkit.AkkaSpec;
|
||||
import com.typesafe.config.ConfigFactory;
|
||||
import static akka.pattern.Patterns.ask;
|
||||
|
||||
import static akka.docs.jrouting.CustomRouterDocTestBase.DemocratActor;
|
||||
import static akka.docs.jrouting.CustomRouterDocTestBase.RepublicanActor;
|
||||
import static akka.docs.jrouting.CustomRouterDocTestBase.Message.*;
|
||||
|
||||
public class CustomRouterDocTestBase {
|
||||
|
||||
ActorSystem system;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
system = ActorSystem.create("MySystem", AkkaSpec.testConf());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
//#crTest
|
||||
@Test
|
||||
public void countVotesAsIntendedNotAsInFlorida() {
|
||||
ActorRef routedActor = system.actorOf(new Props().withRouter(new VoteCountRouter()));
|
||||
routedActor.tell(DemocratVote);
|
||||
routedActor.tell(DemocratVote);
|
||||
routedActor.tell(RepublicanVote);
|
||||
routedActor.tell(DemocratVote);
|
||||
routedActor.tell(RepublicanVote);
|
||||
Timeout timeout = new Timeout(Duration.parse("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
|
||||
|
||||
//#crActors
|
||||
public static 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static 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
|
||||
|
||||
//#crRouter
|
||||
public static class VoteCountRouter extends CustomRouterConfig {
|
||||
|
||||
//#crRoute
|
||||
@Override
|
||||
public CustomRoute createCustomRoute(Props props, RouteeProvider routeeProvider) {
|
||||
final ActorRef democratActor = routeeProvider.context().actorOf(new Props(DemocratActor.class), "d");
|
||||
final ActorRef republicanActor = routeeProvider.context().actorOf(new Props(RepublicanActor.class), "r");
|
||||
List<ActorRef> routees = Arrays.asList(new ActorRef[] { democratActor, republicanActor });
|
||||
|
||||
//#crRegisterRoutees
|
||||
routeeProvider.registerRoutees(routees);
|
||||
//#crRegisterRoutees
|
||||
|
||||
//#crRoutingLogic
|
||||
return new CustomRoute() {
|
||||
@Override
|
||||
public Iterable<Destination> destinationsFor(ActorRef sender, Object msg) {
|
||||
switch ((Message) msg) {
|
||||
case DemocratVote:
|
||||
case DemocratCountResult:
|
||||
return Arrays.asList(new Destination[] { new Destination(sender, democratActor) });
|
||||
case RepublicanVote:
|
||||
case RepublicanCountResult:
|
||||
return Arrays.asList(new Destination[] { new Destination(sender, republicanActor) });
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown message: " + msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
//#crRoutingLogic
|
||||
}
|
||||
//#crRoute
|
||||
|
||||
}
|
||||
|
||||
//#crRouter
|
||||
//#CustomRouter
|
||||
|
||||
}
|
||||
48
akka-docs/java/code/akka/docs/jrouting/FibonacciActor.java
Normal file
48
akka-docs/java/code/akka/docs/jrouting/FibonacciActor.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.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()));
|
||||
} 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
|
||||
|
||||
69
akka-docs/java/code/akka/docs/jrouting/ParentActor.java
Normal file
69
akka-docs/java/code/akka/docs/jrouting/ParentActor.java
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.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 akka.util.Duration;
|
||||
import akka.util.Timeout;
|
||||
import akka.dispatch.Future;
|
||||
import akka.dispatch.Await;
|
||||
|
||||
//#parentActor
|
||||
public class ParentActor extends UntypedActor {
|
||||
public void onReceive(Object msg) {
|
||||
if (msg.equals("rrr")) {
|
||||
//#roundRobinRouter
|
||||
ActorRef roundRobinRouter = getContext().actorOf(
|
||||
new Props(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(new Props(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(
|
||||
new Props(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(new Props(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(
|
||||
new Props(FibonacciActor.class).withRouter(new ScatterGatherFirstCompletedRouter(5, Duration
|
||||
.parse("2 seconds"))), "router");
|
||||
Timeout timeout = getContext().system().settings().ActorTimeout();
|
||||
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
|
||||
15
akka-docs/java/code/akka/docs/jrouting/PrintlnActor.java
Normal file
15
akka-docs/java/code/akka/docs/jrouting/PrintlnActor.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.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
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.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(new Props(ExampleActor.class).withRouter(new FromConfig()), "router");
|
||||
//#configurableRouting
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
router.tell(new ExampleActor.Message(i));
|
||||
}
|
||||
|
||||
//#configurableRoutingWithResizer
|
||||
ActorRef router2 = system.actorOf(new Props(ExampleActor.class).withRouter(new FromConfig()), "router2");
|
||||
//#configurableRoutingWithResizer
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
router2.tell(new ExampleActor.Message(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.docs.jrouting;
|
||||
|
||||
import akka.routing.RoundRobinRouter;
|
||||
import akka.routing.DefaultResizer;
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.Props;
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.actor.ActorSystem;
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
ActorSystem system = ActorSystem.create("RPE");
|
||||
//#programmaticRoutingNrOfInstances
|
||||
int nrOfInstances = 5;
|
||||
ActorRef router1 = system.actorOf(new Props(ExampleActor.class).withRouter(new RoundRobinRouter(nrOfInstances)));
|
||||
//#programmaticRoutingNrOfInstances
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
router1.tell(new ExampleActor.Message(i));
|
||||
}
|
||||
|
||||
//#programmaticRoutingRoutees
|
||||
ActorRef actor1 = system.actorOf(new Props(ExampleActor.class));
|
||||
ActorRef actor2 = system.actorOf(new Props(ExampleActor.class));
|
||||
ActorRef actor3 = system.actorOf(new Props(ExampleActor.class));
|
||||
Iterable<ActorRef> routees = Arrays.asList(new ActorRef[] { actor1, actor2, actor3 });
|
||||
ActorRef router2 = system.actorOf(new Props(ExampleActor.class).withRouter(RoundRobinRouter.create(routees)));
|
||||
//#programmaticRoutingRoutees
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
router2.tell(new ExampleActor.Message(i));
|
||||
}
|
||||
|
||||
//#programmaticRoutingWithResizer
|
||||
int lowerBound = 2;
|
||||
int upperBound = 15;
|
||||
DefaultResizer resizer = new DefaultResizer(lowerBound, upperBound);
|
||||
ActorRef router3 = system.actorOf(new Props(ExampleActor.class).withRouter(new RoundRobinRouter(nrOfInstances)));
|
||||
//#programmaticRoutingWithResizer
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
router3.tell(new ExampleActor.Message(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -166,7 +166,7 @@ if not specified otherwise.
|
|||
default-dispatcher {
|
||||
# If negative (or zero) then an unbounded mailbox is used (default)
|
||||
# If positive then a bounded mailbox is used and the capacity is set to the number specified
|
||||
task-queue-size = 1000
|
||||
mailbox-capacity = 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,13 @@ as illustrated in this example:
|
|||
.. includecode:: code/akka/docs/event/LoggingDocTestBase.java
|
||||
:include: imports,my-actor
|
||||
|
||||
The second parameter to the ``Logging.getLogger`` is the source of this logging channel.
|
||||
The source object is translated to a String according to the following rules:
|
||||
The first parameter to ``Logging.getLogger`` could also be any
|
||||
:class:`LoggingBus`, specifically ``system.eventStream()``; in the demonstrated
|
||||
case, the actor system’s address is included in the ``akkaSource``
|
||||
representation of the log source (see `Logging Thread and Akka Source in MDC`_)
|
||||
while in the second case this is not automatically done. The second parameter
|
||||
to ``Logging.getLogger`` is the source of this logging channel. The source
|
||||
object is translated to a String according to the following rules:
|
||||
|
||||
* if it is an Actor or ActorRef, its path is used
|
||||
* in case of a String it is used as is
|
||||
|
|
@ -28,6 +33,13 @@ The source object is translated to a String according to the following rules:
|
|||
The log message may contain argument placeholders ``{}``, which will be substituted if the log level
|
||||
is enabled.
|
||||
|
||||
The Java :class:`Class` of the log source is also included in the generated
|
||||
:class:`LogEvent`. In case of a simple string this is replaced with a “marker”
|
||||
class :class:`akka.event.DummyClassForStringSources` in order to allow special
|
||||
treatment of this case, e.g. in the SLF4J event listener which will then use
|
||||
the string instead of the class’ name for looking up the logger instance to
|
||||
use.
|
||||
|
||||
Event Handler
|
||||
=============
|
||||
|
||||
|
|
@ -83,8 +95,8 @@ creating the ``LoggingAdapter`` correspond to the name of the SL4FJ logger.
|
|||
loglevel = "DEBUG"
|
||||
}
|
||||
|
||||
Logging thread in MDC
|
||||
---------------------
|
||||
Logging Thread and Akka Source in MDC
|
||||
-------------------------------------
|
||||
|
||||
Since the logging is done asynchronously the thread in which the logging was performed is captured in
|
||||
Mapped Diagnostic Context (MDC) with attribute name ``sourceThread``.
|
||||
|
|
@ -96,3 +108,22 @@ With Logback the thread name is available with ``%X{sourceThread}`` specifier wi
|
|||
</layout>
|
||||
</appender>
|
||||
|
||||
.. note::
|
||||
|
||||
It will probably be a good idea to use the ``sourceThread`` MDC value also in
|
||||
non-Akka parts of the application in order to have this property consistently
|
||||
available in the logs.
|
||||
|
||||
Another helpful facility is that Akka captures the actor’s address when
|
||||
instantiating a logger within it, meaning that the full instance identification
|
||||
is available for associating log messages e.g. with members of a router. This
|
||||
information is available in the MDC with attribute name ``akkaSource``::
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout>
|
||||
<pattern>%date{ISO8601} %-5level %logger{36} %X{akkaSource} - %msg%n</pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
For more details on what this attribute contains—also for non-actors—please see
|
||||
`How to Log`_.
|
||||
|
|
|
|||
|
|
@ -9,39 +9,42 @@ For an introduction of remoting capabilities of Akka please see :ref:`remoting`.
|
|||
Preparing your ActorSystem for Remoting
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Akka remoting is a separate jar file. Make sure that you have a dependency from your project to this jar::
|
||||
The Akka remoting is a separate jar file. Make sure that you have the following dependency in your project::
|
||||
|
||||
akka-remote.jar
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-remote</artifactId>
|
||||
<version>2.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
First of all you have to change the actor provider from ``LocalActorRefProvider`` to ``RemoteActorRefProvider``::
|
||||
To enable remote capabilities in your Akka project you should, at a minimum, add the following changes
|
||||
to your ``application.conf`` file::
|
||||
|
||||
akka {
|
||||
actor {
|
||||
provider = "akka.remote.RemoteActorRefProvider"
|
||||
provider = "akka.remote.RemoteActorRefProvider"
|
||||
}
|
||||
}
|
||||
|
||||
After that you must also add the following settings::
|
||||
|
||||
akka {
|
||||
remote {
|
||||
transport = "akka.remote.netty.NettyRemoteSupport"
|
||||
server {
|
||||
# The hostname or ip to bind the remoting to,
|
||||
# InetAddress.getLocalHost.getHostAddress is used if empty
|
||||
hostname = ""
|
||||
|
||||
# The default remote server port clients should connect to.
|
||||
# Default is 2552 (AKKA)
|
||||
hostname = "127.0.0.1"
|
||||
port = 2552
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
These are the bare minimal settings that must exist in order to get started with remoting.
|
||||
There are, of course, more properties that can be tweaked. We refer to the following
|
||||
As you can see in the example above there are four things you need to add to get started:
|
||||
|
||||
* Change provider from ``akka.actor.LocalActorRefProvider`` to ``akka.remote.RemoteActorRefProvider``
|
||||
* Add host name - the machine you want to run the actor system on
|
||||
* Add port number - the port the actor system should listen on
|
||||
|
||||
The example above only illustrates the bare minimum of properties you have to add to enable remoting.
|
||||
There are lots of more properties that are related to remoting in Akka. We refer to the following
|
||||
reference file for more information:
|
||||
|
||||
* `reference.conf of akka-remote <https://github.com/jboner/akka/blob/master/akka-remote/src/main/resources/reference.conf#L39>`_
|
||||
.. literalinclude:: ../../akka-remote/src/main/resources/reference.conf
|
||||
:language: none
|
||||
|
||||
Looking up Remote Actors
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -66,7 +69,7 @@ The "app" in this case refers to the name of the ``ActorSystem``::
|
|||
actor {
|
||||
deployment {
|
||||
/serviceA/retrieval {
|
||||
remote = “akka://app@10.0.0.1:2552”
|
||||
remote = "akka://app@10.0.0.1:2552"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -103,10 +106,10 @@ This is also done via configuration::
|
|||
actor {
|
||||
deployment {
|
||||
/serviceA/aggregation {
|
||||
router = “round-robin”
|
||||
router = "round-robin"
|
||||
nr-of-instances = 10
|
||||
routees {
|
||||
nodes = [“akka://app@10.0.0.2:2552”, “akka://app@10.0.0.3:2552”]
|
||||
target {
|
||||
nodes = ["akka://app@10.0.0.2:2552", "akka://app@10.0.0.3:2552"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,270 @@
|
|||
Routing (Java)
|
||||
==============
|
||||
|
||||
This part of the documentation is not done.
|
||||
.. sidebar:: Contents
|
||||
|
||||
We continuously strive to add and improve the documentation so you may want to have a
|
||||
look at the `snapshot repository <http://akka.io/docs/akka/snapshot/>`_.
|
||||
.. contents:: :local:
|
||||
|
||||
Akka-core includes some building blocks to build more complex message flow handlers, they are listed and explained below:
|
||||
|
||||
Router
|
||||
------
|
||||
|
||||
A Router is an actor that routes incoming messages to outbound actors.
|
||||
The router routes the messages sent to it to its underlying actors called 'routees'.
|
||||
|
||||
Akka comes with some defined routers out of the box, but as you will see in this chapter it
|
||||
is really easy to create your own. The routers shipped with Akka are:
|
||||
|
||||
* ``akka.routing.RoundRobinRouter``
|
||||
* ``akka.routing.RandomRouter``
|
||||
* ``akka.routing.SmallestMailboxRouter``
|
||||
* ``akka.routing.BroadcastRouter``
|
||||
* ``akka.routing.ScatterGatherFirstCompletedRouter``
|
||||
|
||||
Routers Explained
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
This is an example of how to create a router that is defined in configuration:
|
||||
|
||||
.. includecode:: ../scala/code/akka/docs/routing/RouterViaConfigExample.scala#config
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/RouterViaConfigExample.java#configurableRouting
|
||||
|
||||
This is an example of how to programatically create a router and set the number of routees it should create:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/RouterViaProgramExample.java#programmaticRoutingNrOfInstances
|
||||
|
||||
You can also give the router already created routees as in:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/RouterViaProgramExample.java#programmaticRoutingRoutees
|
||||
|
||||
When you create a router programatically you define the number of routees *or* you pass already created routees to it.
|
||||
If you send both parameters to the router *only* the latter will be used, i.e. ``nrOfInstances`` is disregarded.
|
||||
|
||||
*It is also worth pointing out that if you define the ``router`` in the configuration file then this value will be used
|
||||
instead of any programmatically sent parameters.*
|
||||
|
||||
Once you have the router actor it is just to send messages to it as you would to any actor:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
router.tell(new MyMsg());
|
||||
|
||||
The router will apply its behavior to the message it receives and forward it to the routees.
|
||||
|
||||
Router usage
|
||||
^^^^^^^^^^^^
|
||||
|
||||
In this section we will describe how to use the different router types.
|
||||
First we need to create some actors that will be used in the examples:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/PrintlnActor.java#printlnActor
|
||||
|
||||
and
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/FibonacciActor.java#fibonacciActor
|
||||
|
||||
RoundRobinRouter
|
||||
****************
|
||||
Routes in a `round-robin <http://en.wikipedia.org/wiki/Round-robin>`_ fashion to its routees.
|
||||
Code example:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/ParentActor.java#roundRobinRouter
|
||||
|
||||
When run you should see a similar output to this:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
Received message '1' in actor $b
|
||||
Received message '2' in actor $c
|
||||
Received message '3' in actor $d
|
||||
Received message '6' in actor $b
|
||||
Received message '4' in actor $e
|
||||
Received message '8' in actor $d
|
||||
Received message '5' in actor $f
|
||||
Received message '9' in actor $e
|
||||
Received message '10' in actor $f
|
||||
Received message '7' in actor $c
|
||||
|
||||
If you look closely to the output you can see that each of the routees received two messages which
|
||||
is exactly what you would expect from a round-robin router to happen.
|
||||
(The name of an actor is automatically created in the format ``$letter`` unless you specify it -
|
||||
hence the names printed above.)
|
||||
|
||||
RandomRouter
|
||||
************
|
||||
As the name implies this router type selects one of its routees randomly and forwards
|
||||
the message it receives to this routee.
|
||||
This procedure will happen each time it receives a message.
|
||||
Code example:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/ParentActor.java#randomRouter
|
||||
|
||||
When run you should see a similar output to this:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
Received message '1' in actor $e
|
||||
Received message '2' in actor $c
|
||||
Received message '4' in actor $b
|
||||
Received message '5' in actor $d
|
||||
Received message '3' in actor $e
|
||||
Received message '6' in actor $c
|
||||
Received message '7' in actor $d
|
||||
Received message '8' in actor $e
|
||||
Received message '9' in actor $d
|
||||
Received message '10' in actor $d
|
||||
|
||||
The result from running the random router should be different, or at least random, every time you run it.
|
||||
Try to run it a couple of times to verify its behavior if you don't trust us.
|
||||
|
||||
SmallestMailboxRouter
|
||||
*********************
|
||||
A Router that tries to send to the non-suspended routee with fewest messages in mailbox.
|
||||
The selection is done in this order:
|
||||
|
||||
* pick any idle routee (not processing message) with empty mailbox
|
||||
* pick any routee with empty mailbox
|
||||
* pick routee with fewest pending messages in mailbox
|
||||
* pick any remote routee, remote actors are consider lowest priority,
|
||||
since their mailbox size is unknown
|
||||
|
||||
Code example:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/ParentActor.java#smallestMailboxRouter
|
||||
|
||||
BroadcastRouter
|
||||
***************
|
||||
A broadcast router forwards the message it receives to *all* its routees.
|
||||
Code example:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/ParentActor.java#broadcastRouter
|
||||
|
||||
When run you should see a similar output to this:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
Received message 'this is a broadcast message' in actor $f
|
||||
Received message 'this is a broadcast message' in actor $d
|
||||
Received message 'this is a broadcast message' in actor $e
|
||||
Received message 'this is a broadcast message' in actor $c
|
||||
Received message 'this is a broadcast message' in actor $b
|
||||
|
||||
As you can see here above each of the routees, five in total, received the broadcast message.
|
||||
|
||||
ScatterGatherFirstCompletedRouter
|
||||
*********************************
|
||||
The ScatterGatherFirstCompletedRouter will send the message on to all its routees as a future.
|
||||
It then waits for first result it gets back. This result will be sent back to original sender.
|
||||
Code example:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/ParentActor.java#scatterGatherFirstCompletedRouter
|
||||
|
||||
When run you should see this:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
The result of calculating Fibonacci for 10 is 55
|
||||
|
||||
From the output above you can't really see that all the routees performed the calculation, but they did!
|
||||
The result you see is from the first routee that returned its calculation to the router.
|
||||
|
||||
Broadcast Messages
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There is a special type of message that will be sent to all routees regardless of the router.
|
||||
This message is called ``Broadcast`` and is used in the following manner:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
router.tell(new Broadcast("Watch out for Davy Jones' locker"));
|
||||
|
||||
Only the actual message is forwarded to the routees, i.e. "Watch out for Davy Jones' locker" in the example above.
|
||||
It is up to the routee implementation whether to handle the broadcast message or not.
|
||||
|
||||
Dynamically Resizable Routers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All routers can be used with a fixed number of routees or with a resize strategy to adjust the number
|
||||
of routees dynamically.
|
||||
|
||||
This is an example of how to create a resizable router that is defined in configuration:
|
||||
|
||||
.. includecode:: ../scala/code/akka/docs/routing/RouterViaConfigExample.scala#config-resize
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/RouterViaConfigExample.java#configurableRoutingWithResizer
|
||||
|
||||
Several more configuration options are availble and described in ``akka.actor.deployment.default.resizer``
|
||||
section of the reference :ref:`configuration`.
|
||||
|
||||
This is an example of how to programatically create a resizable router:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/RouterViaProgramExample.java#programmaticRoutingWithResizer
|
||||
|
||||
*It is also worth pointing out that if you define the ``router`` in the configuration file then this value
|
||||
will be used instead of any programmatically sent parameters.*
|
||||
|
||||
Custom Router
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
You can also create your own router should you not find any of the ones provided by Akka sufficient for your needs.
|
||||
In order to roll your own router you have to fulfill certain criteria which are explained in this section.
|
||||
|
||||
The router created in this example is a simple vote counter. It will route the votes to specific vote counter actors.
|
||||
In this case we only have two parties the Republicans and the Democrats. We would like a router that forwards all
|
||||
democrat related messages to the Democrat actor and all republican related messages to the Republican actor.
|
||||
|
||||
We begin with defining the class:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#crRouter
|
||||
:exclude: crRoute
|
||||
|
||||
The next step is to implement the ``createCustomRoute`` method in the class just defined:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#crRoute
|
||||
|
||||
As you can see above we start off by creating the routees and put them in a collection.
|
||||
|
||||
Make sure that you don't miss to implement the line below as it is *really* important.
|
||||
It registers the routees internally and failing to call this method will
|
||||
cause a ``ActorInitializationException`` to be thrown when the router is used.
|
||||
Therefore always make sure to do the following in your custom router:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#crRegisterRoutees
|
||||
|
||||
The routing logic is where your magic sauce is applied. In our example it inspects the message types
|
||||
and forwards to the correct routee based on this:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#crRoutingLogic
|
||||
|
||||
As you can see above what's returned in the ``CustomRoute`` function, which defines the mapping
|
||||
from incoming sender/message to a ``List`` of ``Destination(sender, routee)``.
|
||||
The sender is what "parent" the routee should see - changing this could be useful if you for example want
|
||||
another actor than the original sender to intermediate the result of the routee (if there is a result).
|
||||
For more information about how to alter the original sender we refer to the source code of
|
||||
`ScatterGatherFirstCompletedRouter <https://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/akka/routing/Routing.scala#L375>`_
|
||||
|
||||
All in all the custom router looks like this:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#CustomRouter
|
||||
|
||||
If you are interested in how to use the VoteCountRouter it looks like this:
|
||||
|
||||
.. includecode:: code/akka/docs/jrouting/CustomRouterDocTestBase.java#crTest
|
||||
|
||||
Configured Custom Router
|
||||
************************
|
||||
|
||||
It is possible to define configuration properties for custom routers. In the ``router`` property of the deployment
|
||||
configuration you define the fully qualified class name of the router class. The router class must extend
|
||||
``akka.routing.CustomRouterConfig`` and and have constructor with ``com.typesafe.config.Config`` parameter.
|
||||
The deployment section of the configuration is passed to the constructor.
|
||||
|
||||
Custom Resizer
|
||||
**************
|
||||
|
||||
A router with dynamically resizable number of routees is implemented by providing a ``akka.routing.Resizer``
|
||||
in ``resizer`` method of the ``RouterConfig``. See ``akka.routing.DefaultResizer`` for inspiration
|
||||
of how to write your own resize strategy.
|
||||
|
||||
You can also get some ideas of the routing by looking at the corresponding :ref:`routing-scala` documentation.
|
||||
|
|
@ -21,7 +21,7 @@ Usage
|
|||
Configuration
|
||||
-------------
|
||||
|
||||
For Akka to know which ``Serializer`` to use for what, you need edit your Akka Configuration,
|
||||
For Akka to know which ``Serializer`` to use for what, you need edit your :ref:`configuration`,
|
||||
in the "akka.actor.serializers"-section you bind names to implementations of the ``akka.serialization.Serializer``
|
||||
you wish to use, like this:
|
||||
|
||||
|
|
@ -90,5 +90,5 @@ which is done by extending ``akka.serialization.JSerializer``, like this:
|
|||
:include: imports,my-own-serializer
|
||||
:exclude: ...
|
||||
|
||||
Then you only need to fill in the blanks, bind it to a name in your Akka Configuration and then
|
||||
Then you only need to fill in the blanks, bind it to a name in your :ref:`configuration` and then
|
||||
list which classes that should be serialized using it.
|
||||
|
|
@ -485,6 +485,16 @@ Use it like this:
|
|||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-actors,poison-pill
|
||||
|
||||
Graceful Stop
|
||||
-------------
|
||||
|
||||
:meth:`gracefulStop` is useful if you need to wait for termination or compose ordered
|
||||
termination of several actors:
|
||||
|
||||
.. includecode:: code/akka/docs/actor/UntypedActorDocTestBase.java
|
||||
:include: import-gracefulStop,gracefulStop
|
||||
|
||||
|
||||
.. _UntypedActor.HotSwap:
|
||||
|
||||
HotSwap
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue