remote deploy docs & provider.getExternalAddressFor (see #1765)
This commit is contained in:
parent
10974acfe8
commit
76bba1f530
10 changed files with 217 additions and 29 deletions
|
|
@ -134,6 +134,14 @@ trait ActorRefProvider {
|
|||
* is usually initiated by stopping the guardian via ActorSystem.stop().
|
||||
*/
|
||||
def terminationFuture: Future[Unit]
|
||||
|
||||
/**
|
||||
* Obtain the address which is to be used within sender references when
|
||||
* sending to the given other address or none if the other address cannot be
|
||||
* reached from this system (i.e. no means of communication known; no
|
||||
* attempt is made to verify actual reachability).
|
||||
*/
|
||||
def getExternalAddressFor(addr: Address): Option[Address]
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -529,6 +537,8 @@ class LocalActorRefProvider(
|
|||
new RoutedActorRef(system, props.withRouter(d.routerConfig), supervisor, path)
|
||||
}
|
||||
}
|
||||
|
||||
def getExternalAddressFor(addr: Address): Option[Address] = if (addr == rootPath.address) Some(addr) else None
|
||||
}
|
||||
|
||||
class LocalDeathWatch(val mapSize: Int) extends DeathWatch with ActorClassification {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ final case class Address(protocol: String, system: String, host: Option[String],
|
|||
|
||||
object Address {
|
||||
def apply(protocol: String, system: String) = new Address(protocol, system)
|
||||
def apply(protocol: String, system: String, host: String, port: Int) = new Address(protocol, system, Some(host), Some(port))
|
||||
}
|
||||
|
||||
object RelativeActorPath {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ final case class Deploy(
|
|||
|
||||
def this(routing: RouterConfig) = this("", ConfigFactory.empty, routing)
|
||||
def this(routing: RouterConfig, scope: Scope) = this("", ConfigFactory.empty, routing, scope)
|
||||
def this(scope: Scope) = this("", ConfigFactory.empty, NoRouter, scope)
|
||||
|
||||
/**
|
||||
* Do a merge between this and the other Deploy, where values from “this” take
|
||||
|
|
|
|||
|
|
@ -41,11 +41,16 @@ guarantee!).
|
|||
How is Remoting Used?
|
||||
---------------------
|
||||
|
||||
We took the idea of transparency to the limit in that there is no API for the
|
||||
remoting layer of Akka: it is purely driven by configuration. Just write your
|
||||
application according to the principles outlined in the previous sections, then
|
||||
specify remote deployment of actor sub-trees in the configuration file. This
|
||||
way, your application can be scaled out without having to touch the code.
|
||||
We took the idea of transparency to the limit in that there is nearly no API
|
||||
for the remoting layer of Akka: it is purely driven by configuration. Just
|
||||
write your application according to the principles outlined in the previous
|
||||
sections, then specify remote deployment of actor sub-trees in the
|
||||
configuration file. This way, your application can be scaled out without having
|
||||
to touch the code. The only piece of the API which allows programmatic
|
||||
influence on remote deployment is that :class:`Props` contain a field which may
|
||||
be set to a specific :class:`Deploy` instance; this has the same effect as
|
||||
putting an equivalent deployment into the configuration file (if both are
|
||||
given, configuration file wins).
|
||||
|
||||
Marking Points for Scaling Up with Routers
|
||||
------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.docs.remoting
|
||||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class RemoteDeploymentDocTest extends RemoteDeploymentDocTestBase with JUnitSuite
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.docs.remoting;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
//#import
|
||||
import akka.actor.ActorRef;
|
||||
import akka.actor.Address;
|
||||
import akka.actor.AddressExtractor;
|
||||
import akka.actor.Deploy;
|
||||
import akka.actor.Props;
|
||||
import akka.actor.ActorSystem;
|
||||
import akka.remote.RemoteScope;
|
||||
//#import
|
||||
|
||||
public class RemoteDeploymentDocTestBase {
|
||||
|
||||
static ActorSystem system;
|
||||
|
||||
@BeforeClass
|
||||
public static void init() {
|
||||
system = ActorSystem.create();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void cleanup() {
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void demonstrateDeployment() {
|
||||
//#make-address
|
||||
Address addr = new Address("akka", "sys", "host", 1234);
|
||||
addr = AddressExtractor.parse("akka://sys@host:1234"); // the same
|
||||
//#make-address
|
||||
//#deploy
|
||||
ActorRef ref = system.actorOf(new Props(RemoteDeploymentDocSpec.Echo.class).withDeploy(new Deploy(new RemoteScope(addr))));
|
||||
//#deploy
|
||||
assert ref.path().address().equals(addr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -36,8 +36,12 @@ to your ``application.conf`` file::
|
|||
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
|
||||
* Add host name - the machine you want to run the actor system on; this host
|
||||
name is exactly what is passed to remote systems in order to identify this
|
||||
system and consequently used for connecting back to this system if need be,
|
||||
hence set it to a reachable IP address or resolvable name in case you want to
|
||||
communicate across the network.
|
||||
* Add port number - the port the actor system should listen on, set to 0 to have it chosen automatically
|
||||
|
||||
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
|
||||
|
|
@ -63,7 +67,7 @@ Creating Actors Remotely
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The configuration below instructs the system to deploy the actor "retrieval” on the specific host "app@10.0.0.1".
|
||||
The "app" in this case refers to the name of the ``ActorSystem``::
|
||||
The "app" in this case refers to the name of the ``ActorSystem`` (only showing deployment section)::
|
||||
|
||||
akka {
|
||||
actor {
|
||||
|
|
@ -88,6 +92,27 @@ As you can see from the example above the following pattern is used to find an `
|
|||
|
||||
akka://<actorsystemname>@<hostname>:<port>/<actor path>
|
||||
|
||||
Programmatic Remote Deployment
|
||||
------------------------------
|
||||
|
||||
To allow dynamically deployed systems, it is also possible to include
|
||||
deployment configuration in the :class:`Props` which are used to create an
|
||||
actor: this information is the equivalent of a deployment section from the
|
||||
configuration file, and if both are given, the external configuration takes
|
||||
precedence.
|
||||
|
||||
With these imports:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocTestBase.java#import
|
||||
|
||||
and a remote address like this:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocTestBase.java#make-address
|
||||
|
||||
you can advise the system to create a child on that remote node like so:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocTestBase.java#deploy
|
||||
|
||||
Serialization
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -122,9 +147,12 @@ the two given target nodes.
|
|||
Description of the Remoting Sample
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The sample application included with the Akka sources demonstrates both, remote
|
||||
deployment and look-up of remote actors. First, let us have a look at the
|
||||
common setup for both scenarios (this is ``common.conf``):
|
||||
There is a more extensive remote example that comes with the Akka distribution.
|
||||
Please have a look here for more information: `Remote Sample
|
||||
<https://github.com/jboner/akka/tree/master/akka-samples/akka-sample-remote>`_
|
||||
This sample demonstrates both, remote deployment and look-up of remote actors.
|
||||
First, let us have a look at the common setup for both scenarios (this is
|
||||
``common.conf``):
|
||||
|
||||
.. includecode:: ../../akka-samples/akka-sample-remote/src/main/resources/common.conf
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package akka.docs.remoting
|
||||
|
||||
import akka.actor.{ ExtendedActorSystem, ActorSystem, Actor, ActorRef }
|
||||
import akka.testkit.{ AkkaSpec, ImplicitSender }
|
||||
//#import
|
||||
import akka.actor.{ Props, Deploy, Address, AddressExtractor }
|
||||
import akka.remote.RemoteScope
|
||||
//#import
|
||||
|
||||
object RemoteDeploymentDocSpec {
|
||||
|
||||
class Echo extends Actor {
|
||||
def receive = {
|
||||
case x ⇒ sender ! self
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RemoteDeploymentDocSpec extends AkkaSpec("""
|
||||
akka.actor.provider = "akka.remote.RemoteActorRefProvider"
|
||||
akka.remote.netty.port = 0
|
||||
""") with ImplicitSender {
|
||||
|
||||
import RemoteDeploymentDocSpec._
|
||||
|
||||
val other = ActorSystem("remote", system.settings.config)
|
||||
val address = other.asInstanceOf[ExtendedActorSystem].provider.getExternalAddressFor(Address("akka", "s", Some("host"), Some(1))).get
|
||||
|
||||
override def atTermination() { other.shutdown() }
|
||||
|
||||
"demonstrate programmatic deployment" in {
|
||||
//#deploy
|
||||
val ref = system.actorOf(Props[Echo].withDeploy(Deploy(scope = RemoteScope(address))))
|
||||
//#deploy
|
||||
ref.path.address must be(address)
|
||||
ref ! "test"
|
||||
expectMsgType[ActorRef].path.address must be(address)
|
||||
}
|
||||
|
||||
"demonstrate address extractor" in {
|
||||
//#make-address
|
||||
val one = AddressExtractor("akka://sys@host:1234")
|
||||
val two = Address("akka", "sys", "host", 1234) // this gives the same
|
||||
//#make-address
|
||||
one must be === two
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,11 @@
|
|||
Remoting (Scala)
|
||||
#################
|
||||
|
||||
|
||||
.. sidebar:: Contents
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
For an introduction of remoting capabilities of Akka please see :ref:`remoting`.
|
||||
|
||||
Preparing your ActorSystem for Remoting
|
||||
|
|
@ -32,8 +37,12 @@ to your ``application.conf`` file::
|
|||
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
|
||||
* Add host name - the machine you want to run the actor system on; this host
|
||||
name is exactly what is passed to remote systems in order to identify this
|
||||
system and consequently used for connecting back to this system if need be,
|
||||
hence set it to a reachable IP address or resolvable name in case you want to
|
||||
communicate across the network.
|
||||
* Add port number - the port the actor system should listen on, set to 0 to have it chosen automatically
|
||||
|
||||
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
|
||||
|
|
@ -63,7 +72,7 @@ As you can see from the example above the following pattern is used to find an `
|
|||
|
||||
akka://<actor system>@<hostname>:<port>/<actor path>
|
||||
|
||||
Once you a reference to the actor you can interact with it they same way you would with a local actor, e.g.::
|
||||
Once you obtained a reference to the actor you can interact with it they same way you would with a local actor, e.g.::
|
||||
|
||||
actor ! "Pretty awesome feature"
|
||||
|
||||
|
|
@ -73,18 +82,19 @@ Creating Actors Remotely
|
|||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you want to use the creation functionality in Akka remoting you have to further amend the
|
||||
``application.conf`` file in the following way::
|
||||
``application.conf`` file in the following way (only showing deployment section)::
|
||||
|
||||
akka {
|
||||
actor {
|
||||
provider = "akka.remote.RemoteActorRefProvider"
|
||||
deployment { /sampleActor {
|
||||
deployment {
|
||||
/sampleActor {
|
||||
remote = "akka://sampleActorSystem@127.0.0.1:2553"
|
||||
}}
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The configuration above instructs Akka to react when an actor with path /sampleActor is created, i.e.
|
||||
The configuration above instructs Akka to react when an actor with path ``/sampleActor`` is created, i.e.
|
||||
using ``system.actorOf(Props(...)`, sampleActor)``. This specific actor will not be directly instantiated,
|
||||
but instead the remote daemon of the remote system will be asked to create the actor,
|
||||
which in this sample corresponds to ``sampleActorSystem@127.0.0.1:2553``.
|
||||
|
|
@ -99,12 +109,26 @@ Once you have configured the properties above you would do the following in code
|
|||
``SampleActor`` has to be available to the runtimes using it, i.e. the classloader of the
|
||||
actor systems has to have a JAR containing the class.
|
||||
|
||||
Remote Sample Code
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
Programmatic Remote Deployment
|
||||
------------------------------
|
||||
|
||||
There is a more extensive remote example that comes with the Akka distribution.
|
||||
Please have a look here for more information:
|
||||
`Remote Sample <https://github.com/jboner/akka/tree/master/akka-samples/akka-sample-remote>`_
|
||||
To allow dynamically deployed systems, it is also possible to include
|
||||
deployment configuration in the :class:`Props` which are used to create an
|
||||
actor: this information is the equivalent of a deployment section from the
|
||||
configuration file, and if both are given, the external configuration takes
|
||||
precedence.
|
||||
|
||||
With these imports:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocSpec.scala#import
|
||||
|
||||
and a remote address like this:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocSpec.scala#make-address
|
||||
|
||||
you can advise the system to create a child on that remote node like so:
|
||||
|
||||
.. includecode:: code/akka/docs/remoting/RemoteDeploymentDocSpec.scala#deploy
|
||||
|
||||
Serialization
|
||||
^^^^^^^^^^^^^
|
||||
|
|
@ -140,9 +164,12 @@ the two given target nodes.
|
|||
Description of the Remoting Sample
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The sample application included with the Akka sources demonstrates both, remote
|
||||
deployment and look-up of remote actors. First, let us have a look at the
|
||||
common setup for both scenarios (this is ``common.conf``):
|
||||
There is a more extensive remote example that comes with the Akka distribution.
|
||||
Please have a look here for more information: `Remote Sample
|
||||
<https://github.com/jboner/akka/tree/master/akka-samples/akka-sample-remote>`_
|
||||
This sample demonstrates both, remote deployment and look-up of remote actors.
|
||||
First, let us have a look at the common setup for both scenarios (this is
|
||||
``common.conf``):
|
||||
|
||||
.. includecode:: ../../akka-samples/akka-sample-remote/src/main/resources/common.conf
|
||||
|
||||
|
|
|
|||
|
|
@ -206,6 +206,16 @@ class RemoteActorRefProvider(
|
|||
// we don’t wait for the ACK, because the remote end will process this command before any other message to the new actor
|
||||
actorFor(RootActorPath(path.address) / "remote") ! DaemonMsgCreate(props, deploy, path.toString, supervisor)
|
||||
}
|
||||
|
||||
def getExternalAddressFor(addr: Address): Option[Address] = {
|
||||
val ta = transport.address
|
||||
val ra = rootPath.address
|
||||
addr match {
|
||||
case `ta` | `ra` ⇒ Some(rootPath.address)
|
||||
case Address("akka", _, Some(_), Some(_)) ⇒ Some(transport.address)
|
||||
case _ ⇒ None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait RemoteRef extends ActorRefScope {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue