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().
|
* is usually initiated by stopping the guardian via ActorSystem.stop().
|
||||||
*/
|
*/
|
||||||
def terminationFuture: Future[Unit]
|
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)
|
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 {
|
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 {
|
object Address {
|
||||||
def apply(protocol: String, system: String) = new Address(protocol, system)
|
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 {
|
object RelativeActorPath {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ final case class Deploy(
|
||||||
|
|
||||||
def this(routing: RouterConfig) = this("", ConfigFactory.empty, routing)
|
def this(routing: RouterConfig) = this("", ConfigFactory.empty, routing)
|
||||||
def this(routing: RouterConfig, scope: Scope) = this("", ConfigFactory.empty, routing, scope)
|
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
|
* Do a merge between this and the other Deploy, where values from “this” take
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,16 @@ guarantee!).
|
||||||
How is Remoting Used?
|
How is Remoting Used?
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
We took the idea of transparency to the limit in that there is no API for the
|
We took the idea of transparency to the limit in that there is nearly no API
|
||||||
remoting layer of Akka: it is purely driven by configuration. Just write your
|
for the remoting layer of Akka: it is purely driven by configuration. Just
|
||||||
application according to the principles outlined in the previous sections, then
|
write your application according to the principles outlined in the previous
|
||||||
specify remote deployment of actor sub-trees in the configuration file. This
|
sections, then specify remote deployment of actor sub-trees in the
|
||||||
way, your application can be scaled out without having to touch the code.
|
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
|
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:
|
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``
|
* Change provider from ``akka.actor.LocalActorRefProvider`` to ``akka.remote.RemoteActorRefProvider``
|
||||||
* Add host name - the machine you want to run the actor system on
|
* Add host name - the machine you want to run the actor system on; this host
|
||||||
* Add port number - the port the actor system should listen on
|
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.
|
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
|
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 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 {
|
akka {
|
||||||
actor {
|
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>
|
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
|
Serialization
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
@ -122,9 +147,12 @@ the two given target nodes.
|
||||||
Description of the Remoting Sample
|
Description of the Remoting Sample
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The sample application included with the Akka sources demonstrates both, remote
|
There is a more extensive remote example that comes with the Akka distribution.
|
||||||
deployment and look-up of remote actors. First, let us have a look at the
|
Please have a look here for more information: `Remote Sample
|
||||||
common setup for both scenarios (this is ``common.conf``):
|
<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
|
.. 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)
|
Remoting (Scala)
|
||||||
#################
|
#################
|
||||||
|
|
||||||
|
|
||||||
|
.. sidebar:: Contents
|
||||||
|
|
||||||
|
.. contents:: :local:
|
||||||
|
|
||||||
For an introduction of remoting capabilities of Akka please see :ref:`remoting`.
|
For an introduction of remoting capabilities of Akka please see :ref:`remoting`.
|
||||||
|
|
||||||
Preparing your ActorSystem for 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:
|
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``
|
* Change provider from ``akka.actor.LocalActorRefProvider`` to ``akka.remote.RemoteActorRefProvider``
|
||||||
* Add host name - the machine you want to run the actor system on
|
* Add host name - the machine you want to run the actor system on; this host
|
||||||
* Add port number - the port the actor system should listen on
|
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.
|
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
|
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>
|
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"
|
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
|
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 {
|
akka {
|
||||||
actor {
|
actor {
|
||||||
provider = "akka.remote.RemoteActorRefProvider"
|
deployment {
|
||||||
deployment { /sampleActor {
|
/sampleActor {
|
||||||
remote = "akka://sampleActorSystem@127.0.0.1:2553"
|
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,
|
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,
|
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``.
|
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
|
``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.
|
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.
|
To allow dynamically deployed systems, it is also possible to include
|
||||||
Please have a look here for more information:
|
deployment configuration in the :class:`Props` which are used to create an
|
||||||
`Remote Sample <https://github.com/jboner/akka/tree/master/akka-samples/akka-sample-remote>`_
|
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
|
Serialization
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
@ -140,9 +164,12 @@ the two given target nodes.
|
||||||
Description of the Remoting Sample
|
Description of the Remoting Sample
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The sample application included with the Akka sources demonstrates both, remote
|
There is a more extensive remote example that comes with the Akka distribution.
|
||||||
deployment and look-up of remote actors. First, let us have a look at the
|
Please have a look here for more information: `Remote Sample
|
||||||
common setup for both scenarios (this is ``common.conf``):
|
<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
|
.. 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
|
// 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)
|
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 {
|
trait RemoteRef extends ActorRefScope {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue