From ef0af0b47f9bcaa380a075be7d2f4b807a67eb18 Mon Sep 17 00:00:00 2001 From: Roland Date: Tue, 21 Feb 2012 15:37:51 +0100 Subject: [PATCH] document RemoteRouterConfig, see #1846 - fix Java API - change to pass in Addresses so that validation happens earlier --- .../docs/jrouting/RouterViaProgramExample.java | 11 +++++++++++ akka-docs/java/routing.rst | 12 ++++++++++++ .../docs/routing/RouterViaProgramExample.scala | 10 ++++++++++ akka-docs/scala/routing.rst | 12 ++++++++++++ .../scala/akka/remote/RemoteDeployer.scala | 2 +- .../akka/routing/RemoteRouterConfig.scala | 18 +++++++++--------- .../scala/akka/remote/RemoteRouterSpec.scala | 2 +- 7 files changed, 56 insertions(+), 11 deletions(-) diff --git a/akka-docs/java/code/akka/docs/jrouting/RouterViaProgramExample.java b/akka-docs/java/code/akka/docs/jrouting/RouterViaProgramExample.java index 27e90b63fa..52a721ed0d 100644 --- a/akka-docs/java/code/akka/docs/jrouting/RouterViaProgramExample.java +++ b/akka-docs/java/code/akka/docs/jrouting/RouterViaProgramExample.java @@ -5,10 +5,13 @@ package akka.docs.jrouting; import akka.routing.RoundRobinRouter; import akka.routing.DefaultResizer; +import akka.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.AddressExtractor; import java.util.Arrays; public class RouterViaProgramExample { @@ -67,6 +70,14 @@ public class RouterViaProgramExample { for (int i = 1; i <= 6; i++) { router3.tell(new ExampleActor.Message(i)); } + + //#remoteRoutees + Address addr1 = new Address("akka", "remotesys", "otherhost", 1234); + Address addr2 = AddressExtractor.parse("akka://othersys@anotherhost:1234"); + Address[] addresses = new Address[] { addr1, addr2 }; + ActorRef routerRemote = system.actorOf(new Props(ExampleActor.class) + .withRouter(new RemoteRouterConfig(new RoundRobinRouter(5), addresses))); + //#remoteRoutees } private class CompileCheckJavaDocsForRouting extends UntypedActor { diff --git a/akka-docs/java/routing.rst b/akka-docs/java/routing.rst index aa1daa19db..aeb89c2506 100644 --- a/akka-docs/java/routing.rst +++ b/akka-docs/java/routing.rst @@ -54,6 +54,18 @@ Once you have the router actor it is just to send messages to it as you would to The router will apply its behavior to the message it receives and forward it to the routees. +Remotely Deploying Routees +************************** + +In addition to being able to supply looked-up remote actors as routees, you can +make the router deploy its created children on a set of remote hosts; this will +be done in round-robin fashion. In order to do that, wrap the router +configuration in a :class:`RemoteRouterConfig`, attaching the remote addresses of +the nodes to deploy to. Naturally, this requires your to include the +``akka-remote`` module on your classpath: + +.. includecode:: code/akka/docs/jrouting/RouterViaProgramExample.java#remoteRoutees + How Routing is Designed within Akka ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/akka-docs/scala/code/akka/docs/routing/RouterViaProgramExample.scala b/akka-docs/scala/code/akka/docs/routing/RouterViaProgramExample.scala index 246ddbf5a2..3750e42635 100644 --- a/akka-docs/scala/code/akka/docs/routing/RouterViaProgramExample.scala +++ b/akka-docs/scala/code/akka/docs/routing/RouterViaProgramExample.scala @@ -6,6 +6,7 @@ package akka.docs.routing import akka.routing.RoundRobinRouter import akka.actor.{ ActorRef, Props, Actor, ActorSystem } import akka.routing.DefaultResizer +import akka.routing.RemoteRouterConfig case class Message1(nbr: Int) @@ -40,4 +41,13 @@ object RoutingProgrammaticallyExample extends App { //#programmaticRoutingWithResizer 1 to 6 foreach { i ⇒ router3 ! Message1(i) } + //#remoteRoutees + import akka.actor.{ Address, AddressExtractor } + val addresses = Seq( + Address("akka", "remotesys", "otherhost", 1234), + AddressExtractor("akka://othersys@anotherhost:1234")) + val routerRemote = system.actorOf(Props[ExampleActor1].withRouter( + RemoteRouterConfig(RoundRobinRouter(5), addresses))) + //#remoteRoutees + } \ No newline at end of file diff --git a/akka-docs/scala/routing.rst b/akka-docs/scala/routing.rst index 7071747374..92776fa73f 100644 --- a/akka-docs/scala/routing.rst +++ b/akka-docs/scala/routing.rst @@ -54,6 +54,18 @@ Once you have the router actor it is just to send messages to it as you would to The router will apply its behavior to the message it receives and forward it to the routees. +Remotely Deploying Routees +************************** + +In addition to being able to supply looked-up remote actors as routees, you can +make the router deploy its created children on a set of remote hosts; this will +be done in round-robin fashion. In order to do that, wrap the router +configuration in a :class:`RemoteRouterConfig`, attaching the remote addresses of +the nodes to deploy to. Naturally, this requires your to include the +``akka-remote`` module on your classpath: + +.. includecode:: code/akka/docs/routing/RouterViaProgramExample.scala#remoteRoutees + How Routing is Designed within Akka ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/akka-remote/src/main/scala/akka/remote/RemoteDeployer.scala b/akka-remote/src/main/scala/akka/remote/RemoteDeployer.scala index 1e1068cd5f..61a3459e9d 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteDeployer.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteDeployer.scala @@ -23,7 +23,7 @@ class RemoteDeployer(_settings: ActorSystem.Settings, _pm: DynamicAccess) extend case AddressExtractor(r) ⇒ Some(deploy.copy(scope = RemoteScope(r))) case str ⇒ if (!str.isEmpty) throw new ConfigurationException("unparseable remote node name " + str) - val nodes = deploy.config.getStringList("target.nodes").asScala + val nodes = deploy.config.getStringList("target.nodes").asScala map (AddressExtractor(_)) if (nodes.isEmpty || deploy.routerConfig == NoRouter) d else Some(deploy.copy(routerConfig = RemoteRouterConfig(deploy.routerConfig, nodes))) } diff --git a/akka-remote/src/main/scala/akka/routing/RemoteRouterConfig.scala b/akka-remote/src/main/scala/akka/routing/RemoteRouterConfig.scala index afa94433aa..45e059dab6 100644 --- a/akka-remote/src/main/scala/akka/routing/RemoteRouterConfig.scala +++ b/akka-remote/src/main/scala/akka/routing/RemoteRouterConfig.scala @@ -14,6 +14,9 @@ import akka.config.ConfigurationException import akka.remote.RemoteScope import akka.actor.AddressExtractor import akka.actor.SupervisorStrategy +import akka.actor.Address + +import scala.collection.JavaConverters._ /** * [[akka.routing.RouterConfig]] implementation for remote deployment on defined @@ -21,7 +24,10 @@ import akka.actor.SupervisorStrategy * which makes it possible to mix this with the built-in routers such as * [[akka.routing.RoundRobinRouter]] or custom routers. */ -case class RemoteRouterConfig(local: RouterConfig, nodes: Iterable[String]) extends RouterConfig { +case class RemoteRouterConfig(local: RouterConfig, nodes: Iterable[Address]) extends RouterConfig { + + def this(local: RouterConfig, nodes: java.lang.Iterable[Address]) = this(local, nodes.asScala) + def this(local: RouterConfig, nodes: Array[Address]) = this(local, nodes: Iterable[Address]) override def createRouteeProvider(context: ActorContext) = new RemoteRouteeProvider(nodes, context, resizer) @@ -49,17 +55,11 @@ case class RemoteRouterConfig(local: RouterConfig, nodes: Iterable[String]) exte * * Routee paths may not be combined with remote target nodes. */ -class RemoteRouteeProvider(nodes: Iterable[String], _context: ActorContext, _resizer: Option[Resizer]) +class RemoteRouteeProvider(nodes: Iterable[Address], _context: ActorContext, _resizer: Option[Resizer]) extends RouteeProvider(_context, _resizer) { // need this iterator as instance variable since Resizer may call createRoutees several times - private val nodeAddressIter = { - val nodeAddresses = nodes map { - case AddressExtractor(a) ⇒ a - case x ⇒ throw new ConfigurationException("unparseable remote node " + x) - } - Stream.continually(nodeAddresses).flatten.iterator - } + private val nodeAddressIter = Stream.continually(nodes).flatten.iterator override def createRoutees(props: Props, nrOfInstances: Int, routees: Iterable[String]): IndexedSeq[ActorRef] = (nrOfInstances, routees, nodes) match { diff --git a/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala b/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala index bf79caf847..acf7ba4f40 100644 --- a/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/RemoteRouterSpec.scala @@ -90,7 +90,7 @@ akka.actor.deployment { "deploy its children on remote host driven by programatic definition" in { val router = system.actorOf(Props[Echo].withRouter(new RemoteRouterConfig(RoundRobinRouter(2), - Seq("akka://remote_sys@localhost:12347"))), "blub2") + Seq(Address("akka", "remote_sys", "localhost", 12347)))), "blub2") val replies = for (i ← 1 to 5) yield { router ! "" expectMsgType[ActorRef].path