Remoting
Loading

Remoting

For an introduction of remoting capabilities of Akka please see Location Transparency.

Preparing your ActorSystem for Remoting

The Akka remoting is a separate jar file. Make sure that you have the following dependency in your project:

  1. <dependency>
  2. <groupId>com.typesafe.akka</groupId>
  3. <artifactId>akka-remote_2.10</artifactId>
  4. <version>2.2.5</version>
  5. </dependency>

To enable remote capabilities in your Akka project you should, at a minimum, add the following changes to your application.conf file:

  1. akka {
  2. actor {
  3. provider = "akka.remote.RemoteActorRefProvider"
  4. }
  5. remote {
  6. enabled-transports = ["akka.remote.netty.tcp"]
  7. netty.tcp {
  8. hostname = "127.0.0.1"
  9. port = 2552
  10. }
  11. }
  12. }

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; 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

Note

The port number needs to be unique for each actor system on the same machine even if the actor systems have different names. This is because each actor system has its own network subsystem listening for connections and handling messages as not to interfere with other actor systems.

The example above only illustrates the bare minimum of properties you have to add to enable remoting. All settings are described in Remote Configuration.

Looking up Remote Actors

actorSelection(path) will obtain an ActorSelection to an Actor on a remote node:

  1. ActorSelection selection =
  2. context.actorSelection("akka.tcp://app@10.0.0.1:2552/user/serviceA/worker");

As you can see from the example above the following pattern is used to find an actor on a remote node:

  1. akka.<protocol>://<actorsystemname>@<hostname>:<port>/<actor path>

Once you obtained a selection to the actor you can interact with it they same way you would with a local actor, e.g.:

  1. selection.tell("Pretty awesome feature", getSelf());

To acquire an ActorRef for an ActorSelection you need to send a message to the selection and use the getSender reference of the reply from the actor. There is a built-in Identify message that all Actors will understand and automatically reply to with a ActorIdentity message containing the ActorRef. This can also be done with the resolveOne method of the ActorSelection, which returns a Future of the matching ActorRef.

Note

For more details on how actor addresses and paths are formed and used, please refer to Actor References, Paths and Addresses.

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 (only showing deployment section):

  1. akka {
  2. actor {
  3. deployment {
  4. /sampleActor {
  5. remote = "akka.tcp://sampleActorSystem@127.0.0.1:2553"
  6. }
  7. }
  8. }
  9. }

The configuration above instructs Akka to react when an actor with path /sampleActor is created, i.e. using system.actorOf(new 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.

Once you have configured the properties above you would do the following in code:

  1. ActorRef actor = system.actorOf(Props.create(SampleActor.class), "sampleActor");
  2. actor.tell("Pretty slick", ActorRef.noSender());

The actor class 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.

Note

In order to ensure serializability of Props when passing constructor arguments to the actor being created, do not make the factory a non-static inner class: this will inherently capture a reference to its enclosing object, which in most cases is not serializable. It is best to make a static inner class which implements Creator.

Serializability of all Props can be tested by setting the configuration item akka.actor.serialize-creators=on. Only Props whose deploy has LocalScope are exempt from this check.

Note

You can use asterisks as wildcard matches for the actor path sections, so you could specify: /*/sampleActor and that would match all sampleActor on that level in the hierarchy. You can also use wildcard in the last position to match all actors at a certain level: /someParent/*. Non-wildcard matches always have higher priority to match than wildcards, so: /foo/bar is considered more specific than /foo/* and only the highest priority match is used. Please note that it cannot be used to partially match section, like this: /foo*/bar, /f*o/bar etc.

Programmatic Remote Deployment

To allow dynamically deployed systems, it is also possible to include deployment configuration in the 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:

  1. import akka.actor.ActorRef;
  2. import akka.actor.Address;
  3. import akka.actor.AddressFromURIString;
  4. import akka.actor.Deploy;
  5. import akka.actor.Props;
  6. import akka.actor.ActorSystem;
  7. import akka.remote.RemoteScope;

and a remote address like this:

  1. Address addr = new Address("akka.tcp", "sys", "host", 1234);
  2. addr = AddressFromURIString.parse("akka.tcp://sys@host:1234"); // the same

you can advise the system to create a child on that remote node like so:

  1. ActorRef ref = system.actorOf(Props.create(SampleActor.class).withDeploy(
  2. new Deploy(new RemoteScope(addr))));

Watching Remote Actors

Watching a remote actor is not different than watching a local actor, as described in Lifecycle Monitoring aka DeathWatch.

Warning

Caveat: Watching an ActorRef acquired with actorFor does not trigger Terminated for lost connections. actorFor is deprecated in favor of actorSelection. Acquire the ActorRef to watch with Identify and ActorIdentity as described in Identifying Actors via Actor Selection.

Failure Detector

Under the hood remote death watch uses heartbeat messages and a failure detector to generate Terminated message from network failures and JVM crashes, in addition to graceful termination of watched actor.

The heartbeat arrival times is interpreted by an implementation of The Phi Accrual Failure Detector.

The suspicion level of failure is given by a value called phi. The basic idea of the phi failure detector is to express the value of phi on a scale that is dynamically adjusted to reflect current network conditions.

The value of phi is calculated as:

  1. phi = -log10(1 - F(timeSinceLastHeartbeat))

where F is the cumulative distribution function of a normal distribution with mean and standard deviation estimated from historical heartbeat inter-arrival times.

In the Remote Configuration you can adjust the akka.remote.watch-failure-detector.threshold to define when a phi value is considered to be a failure.

A low threshold is prone to generate many false positives but ensures a quick detection in the event of a real crash. Conversely, a high threshold generates fewer mistakes but needs more time to detect actual crashes. The default threshold is 10 and is appropriate for most situations. However in cloud environments, such as Amazon EC2, the value could be increased to 12 in order to account for network issues that sometimes occur on such platforms.

The following chart illustrates how phi increase with increasing time since the previous heartbeat.

../_images/phi1.png

Phi is calculated from the mean and standard deviation of historical inter arrival times. The previous chart is an example for standard deviation of 200 ms. If the heartbeats arrive with less deviation the curve becomes steeper, i.e. it is possible to determine failure more quickly. The curve looks like this for a standard deviation of 100 ms.

../_images/phi2.png

To be able to survive sudden abnormalities, such as garbage collection pauses and transient network failures the failure detector is configured with a margin, akka.remote.watch-failure-detector.acceptable-heartbeat-pause. You may want to adjust the Remote Configuration of this depending on you environment. This is how the curve looks like for acceptable-heartbeat-pause configured to 3 seconds.

../_images/phi3.png

Serialization

When using remoting for actors you must ensure that the props and messages used for those actors are serializable. Failing to do so will cause the system to behave in an unintended way.

For more information please see Serialization

Routers with Remote Destinations

It is absolutely feasible to combine remoting with Routing. This is also done via configuration:

  1. akka {
  2. actor {
  3. deployment {
  4. /serviceA/aggregation {
  5. router = "round-robin"
  6. nr-of-instances = 10
  7. target {
  8. nodes = ["akka.tcp://app@10.0.0.2:2552", "akka://app@10.0.0.3:2552"]
  9. }
  10. }
  11. }
  12. }
  13. }

This configuration setting will clone the actor “aggregation” 10 times and deploy it evenly distributed across the two given target nodes.

Description of the Remoting Sample

There is a more extensive remote example that comes with the Akka distribution. Please have a look here for more information: Remote Sample 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):

  1. akka {
  2.  
  3. actor {
  4. provider = "akka.remote.RemoteActorRefProvider"
  5. }
  6.  
  7. remote {
  8. netty.tcp {
  9. hostname = "127.0.0.1"
  10. }
  11. }
  12.  
  13. # Uncomment the following four lines to employ the 'secure cookie handshake'
  14. # This requires the client to have the known secure-cookie and properly
  15. # transmit it to the server upon connection. Because both the client and server
  16. # programs use this common.conf file, they will both have the cookie
  17. #remote {
  18. # secure-cookie = "0009090D040C030E03070D0509020F050B080400"
  19. # require-cookie = on
  20. #}
  21. }

This enables the remoting by installing the RemoteActorRefProvider and chooses the default remote transport. All other options will be set specifically for each show case.

Note

Be sure to replace the default IP 127.0.0.1 with the real address the system is reachable by if you deploy onto multiple machines!

Remote Lookup

In order to look up a remote actor, that one must be created first. For this purpose, we configure an actor system to listen on port 2552 (this is a snippet from application.conf):

  1. calculator {
  2. include "common"
  3.  
  4. akka {
  5. # LISTEN on tcp port 2552
  6. remote.netty.tcp.port = 2552
  7. }
  8. }

Then the actor must be created. For all code which follows, assume these imports:

  1. import akka.actor.ActorRef;
  2. import akka.actor.ActorSystem;
  3. import akka.actor.Props;
  4. import akka.actor.UntypedActor;
  5. import akka.kernel.Bootable;
  6. import com.typesafe.config.ConfigFactory;

The actor doing the work will be this one:

  1. public class JSimpleCalculatorActor extends UntypedActor {
  2. @Override
  3. public void onReceive(Object message) {
  4.  
  5. if (message instanceof Op.Add) {
  6. Op.Add add = (Op.Add) message;
  7. System.out.println("Calculating " + add.getN1() + " + " + add.getN2());
  8. getSender().tell(new Op.AddResult(
  9. add.getN1(), add.getN2(), add.getN1() + add.getN2()),
  10. getSelf());
  11.  
  12. } else if (message instanceof Op.Subtract) {
  13. Op.Subtract subtract = (Op.Subtract) message;
  14. System.out.println("Calculating " + subtract.getN1() + " - " +
  15. subtract.getN2());
  16. getSender().tell(new Op.SubtractResult(
  17. subtract.getN1(), subtract.getN2(), subtract.getN1() - subtract.getN2()),
  18. getSelf());
  19.  
  20. } else {
  21. unhandled(message);
  22. }
  23. }
  24. }
  25. // #actor

and we start it within an actor system using the above configuration

  1. public class JCalculatorApplication implements Bootable {
  2. private ActorSystem system;
  3.  
  4. public JCalculatorApplication() {
  5. system = ActorSystem.create("CalculatorApplication", ConfigFactory.load()
  6. .getConfig("calculator"));
  7. ActorRef actor = system.actorOf(Props.create(JSimpleCalculatorActor.class),
  8. "simpleCalculator");
  9. }
  10.  
  11. @Override
  12. public void startup() {
  13. }
  14.  
  15. @Override
  16. public void shutdown() {
  17. system.shutdown();
  18. }
  19. }
  20. // #setup

With the service actor up and running, we may look it up from another actor system, which will be configured to use port 2553 (this is a snippet from application.conf).

  1. remotelookup {
  2. include "common"
  3.  
  4. akka {
  5. remote.netty.tcp.port = 2553
  6. }
  7. }

The actor which will query the calculator is a quite simple one for demonstration purposes

  1. public class JLookupActor extends UntypedActor {
  2.  
  3. private final String path;
  4. private ActorRef remoteActor = null;
  5.  
  6. public JLookupActor(String path) {
  7. this.path = path;
  8. sendIdentifyRequest();
  9. }
  10.  
  11. private void sendIdentifyRequest() {
  12. getContext().actorSelection(path).tell(new Identify(path), getSelf());
  13. }
  14.  
  15. @Override
  16. public void onReceive(Object message) throws Exception {
  17.  
  18. if (message instanceof ActorIdentity) {
  19. remoteActor = ((ActorIdentity) message).getRef();
  20.  
  21. } else if (message.equals(ReceiveTimeout.getInstance())) {
  22. sendIdentifyRequest();
  23.  
  24. } else if (remoteActor == null) {
  25. System.out.println("Not ready yet");
  26.  
  27. } else if (message instanceof Op.MathOp) {
  28. // send message to server actor
  29. remoteActor.tell(message, getSelf());
  30.  
  31. } else if (message instanceof Op.AddResult) {
  32. Op.AddResult result = (Op.AddResult) message;
  33. System.out.printf("Add result: %d + %d = %d\n", result.getN1(),
  34. result.getN2(), result.getResult());
  35.  
  36. } else if (message instanceof Op.SubtractResult) {
  37. Op.SubtractResult result = (Op.SubtractResult) message;
  38. System.out.printf("Sub result: %d - %d = %d\n", result.getN1(),
  39. result.getN2(), result.getResult());
  40.  
  41. } else {
  42. unhandled(message);
  43. }
  44. }
  45. }

and it is created from an actor system using the aforementioned client’s config.

  1. public class JLookupApplication implements Bootable {
  2. private ActorSystem system;
  3. private ActorRef actor;
  4.  
  5. public JLookupApplication() {
  6. system = ActorSystem.create("LookupApplication", ConfigFactory.load().getConfig(
  7. "remotelookup"));
  8. final String path =
  9. "akka.tcp://CalculatorApplication@127.0.0.1:2552/user/simpleCalculator";
  10. actor = system.actorOf(Props.create(JLookupActor.class, path), "lookupActor");
  11. }
  12.  
  13. public void doSomething(Op.MathOp mathOp) {
  14. actor.tell(mathOp, null);
  15. }
  16.  
  17. @Override
  18. public void startup() {
  19. }
  20.  
  21. @Override
  22. public void shutdown() {
  23. system.shutdown();
  24. }
  25. }
  26. // #setup

Requests which come in via doSomething will be sent to the client actor, which will use the actor reference that was identified earlier. Observe how the actor system name using in actorSelection matches the remote system’s name, as do IP and port number. Top-level actors are always created below the "/user" guardian, which supervises them.

Remote Deployment

Creating remote actors instead of looking them up is not visible in the source code, only in the configuration file. This section is used in this scenario (this is a snippet from application.conf):

  1. remotecreation {
  2. include "common"
  3.  
  4. akka {
  5. actor {
  6. deployment {
  7. /advancedCalculator {
  8. remote = "akka.tcp://CalculatorApplication@127.0.0.1:2552"
  9. }
  10. }
  11. }
  12.  
  13. remote.netty.tcp.port = 2554
  14. }
  15. }

For all code which follows, assume these imports:

  1. import akka.actor.ActorRef;
  2. import akka.actor.ActorSystem;
  3. import akka.actor.Props;
  4. import akka.actor.UntypedActor;
  5. import akka.kernel.Bootable;
  6. import com.typesafe.config.ConfigFactory;

The server actor can multiply or divide numbers:

  1. public class JAdvancedCalculatorActor extends UntypedActor {
  2. @Override
  3. public void onReceive(Object message) throws Exception {
  4.  
  5. if (message instanceof Op.Multiply) {
  6. Op.Multiply multiply = (Op.Multiply) message;
  7. System.out.println("Calculating " + multiply.getN1() + " * "
  8. + multiply.getN2());
  9. getSender().tell(
  10. new Op.MultiplicationResult(multiply.getN1(), multiply.getN2(),
  11. multiply.getN1() * multiply.getN2()), getSelf());
  12.  
  13. } else if (message instanceof Op.Divide) {
  14. Op.Divide divide = (Op.Divide) message;
  15. System.out.println("Calculating " + divide.getN1() + " / "
  16. + divide.getN2());
  17. getSender().tell(
  18. new Op.DivisionResult(divide.getN1(), divide.getN2(), divide.getN1()
  19. / divide.getN2()), getSelf());
  20.  
  21. } else {
  22. unhandled(message);
  23. }
  24. }
  25. }
  26. // #actor

The client actor looks like in the previous example

  1. public class JCreationActor extends UntypedActor {
  2.  
  3. private final ActorRef remoteActor;
  4.  
  5. public JCreationActor(ActorRef remoteActor) {
  6. this.remoteActor = remoteActor;
  7. }
  8.  
  9. @Override
  10. public void onReceive(Object message) throws Exception {
  11.  
  12. if (message instanceof Op.MathOp) {
  13. // send message to server actor
  14. remoteActor.tell(message, getSelf());
  15.  
  16. } else if (message instanceof Op.MultiplicationResult) {
  17. Op.MultiplicationResult result = (Op.MultiplicationResult) message;
  18. System.out.printf("Mul result: %d * %d = %d\n",
  19. result.getN1(), result.getN2(), result.getResult());
  20.  
  21. } else if (message instanceof Op.DivisionResult) {
  22. Op.DivisionResult result = (Op.DivisionResult) message;
  23. System.out.printf("Div result: %.0f / %d = %.2f\n",
  24. result.getN1(), result.getN2(), result.getResult());
  25.  
  26. } else {
  27. unhandled(message);
  28. }
  29. }
  30. }

but the setup uses only actorOf:

  1. public class JCreationApplication implements Bootable {
  2. private ActorSystem system;
  3. private ActorRef actor;
  4.  
  5. public JCreationApplication() {
  6. system = ActorSystem.create("CreationApplication", ConfigFactory.load()
  7. .getConfig("remotecreation"));
  8. final ActorRef remoteActor = system.actorOf(Props.create(
  9. JAdvancedCalculatorActor.class), "advancedCalculator");
  10. actor = system.actorOf(Props.create(JCreationActor.class, remoteActor),
  11. "creationActor");
  12.  
  13. }
  14.  
  15. public void doSomething(Op.MathOp mathOp) {
  16. actor.tell(mathOp, null);
  17. }
  18.  
  19. @Override
  20. public void startup() {
  21. }
  22.  
  23. @Override
  24. public void shutdown() {
  25. system.shutdown();
  26. }
  27. }

Observe how the name of the server actor matches the deployment given in the configuration file, which will transparently delegate the actor creation to the remote node.

Pluggable transport support

Akka can be configured to use various transports to communicate with remote systems. The core component of this feature is the akka.remote.Transport SPI. Transport implementations must extend this trait. Transports can be loaded by setting the akka.remote.enabled-transports configuration key to point to one or more configuration sections containing driver descriptions.

An example of setting up the default Netty based SSL driver as default:

  1. akka {
  2. remote {
  3. enabled-transports = [akka.remote.netty.ssl]
  4.  
  5. netty.ssl.security {
  6. key-store = "mykeystore"
  7. trust-store = "mytruststore"
  8. key-store-password = "changeme"
  9. key-password = "changeme"
  10. trust-store-password = "changeme"
  11. protocol = "TLSv1"
  12. random-number-generator = "AES128CounterSecureRNG"
  13. enabled-algorithms = [TLS_RSA_WITH_AES_128_CBC_SHA]
  14. }
  15. }
  16. }

An example of setting up a custom transport implementation:

  1. akka {
  2. remote {
  3. applied-transports = ["akka.remote.mytransport"]
  4.  
  5. mytransport {
  6. # The transport-class configuration entry is required, and
  7. # it must contain the fully qualified name of the transport
  8. # implementation
  9. transport-class = "my.package.MyTransport"
  10.  
  11. # It is possible to decorate Transports with additional services.
  12. # Adapters should be registered in the "adapters" sections to
  13. # be able to apply them to transports
  14. applied-adapters = []
  15.  
  16. # Driver specific configuration options has to be in the same
  17. # section:
  18. some-config = foo
  19. another-config = bar
  20. }

Remote Events

It is possible to listen to events that occur in Akka Remote, and to subscribe/unsubscribe to these events you simply register as listener to the below described types in on the ActorSystem.eventStream.

Note

To subscribe to any remote event, subscribe to RemotingLifecycleEvent. To subscribe to events related only to the lifecycle of associations, subscribe to akka.remote.AssociationEvent.

Note

The use of term "Association" instead of "Connection" reflects that the remoting subsystem may use connectionless transports, but an association similar to transport layer connections is maintained between endpoints by the Akka protocol.

By default an event listener is registered which logs all of the events described below. This default was chosen to help setting up a system, but it is quite common to switch this logging off once that phase of the project is finished.

Note

In order to switch off the logging, set akka.remote.log-remote-lifecycle-events = off in your application.conf.

To be notified when an association is over ("disconnected") listen to DisassociatedEvent which holds the direction of the association (inbound or outbound) and the addresses of the involved parties.

To be notified when an association is successfully established ("connected") listen to AssociatedEvent which holds the direction of the association (inbound or outbound) and the addresses of the involved parties.

To intercept errors directly related to associations, listen to AssociationErrorEvent which holds the direction of the association (inbound or outbound), the addresses of the involved parties and the Throwable cause.

To be notified when the remoting subsystem is ready to accept associations, listen to RemotingListenEvent which contains the addresses the remoting listens on.

To be notified when the remoting subsystem has been shut down, listen to RemotingShutdownEvent.

To intercept generic remoting related errors, listen to RemotingErrorEvent which holds the Throwable cause.

Remote Security

Akka provides a couple of ways to enhance security between remote nodes (client/server):

  • Untrusted Mode
  • Security Cookie Handshake

Untrusted Mode

As soon as an actor system can connect to another remotely, it may in principle send any possible message to any actor contained within that remote system. One example may be sending a PoisonPill to the system guardian, shutting that system down. This is not always desired, and it can be disabled with the following setting:

  1. akka.remote.untrusted-mode = on

This disallows sending of system messages (actor life-cycle commands, DeathWatch, etc.) and any message extending PossiblyHarmful to the system on which this flag is set. Should a client send them nonetheless they are dropped and logged (at DEBUG level in order to reduce the possibilities for a denial of service attack). PossiblyHarmful covers the predefined messages like PoisonPill and Kill, but it can also be added as a marker trait to user-defined messages.

In summary, the following operations are ignored by a system configured in untrusted mode when incoming via the remoting layer:

  • remote deployment (which also means no remote supervision)
  • remote DeathWatch
  • system.stop(), PoisonPill, Kill
  • sending any message which extends from the PossiblyHarmful marker interface, which includes Terminated

Note

Enabling the untrusted mode does not remove the capability of the client to freely choose the target of its message sends, which means that messages not prohibited by the above rules can be sent to any actor in the remote system. It is good practice for a client-facing system to only contain a well-defined set of entry point actors, which then forward requests (possibly after performing validation) to another actor system containing the actual worker actors. If messaging between these two server-side systems is done using local ActorRef (they can be exchanged safely between actor systems within the same JVM), you can restrict the messages on this interface by marking them PossiblyHarmful so that a client cannot forge them.

SSL

SSL can be used as the remote transport by adding akka.remote.netty.ssl to the enabled-transport configuration section. See a description of the settings in the Remote Configuration section.

The SSL support is implemented with Java Secure Socket Extension, please consult the offical Java Secure Socket Extension documentation and related resources for troubleshooting.

Note

When using SHA1PRNG on Linux it's recommended specify -Djava.security.egd=file:/dev/./urandom as argument to the JVM to prevent blocking. It is NOT as secure because it reuses the seed. Use '/dev/./urandom', not '/dev/urandom' as that doesn't work according to Bug ID: 6202721.

Remote Configuration

There are lots of configuration properties that are related to remoting in Akka. We refer to the following reference file for more information:

  1. #####################################
  2. # Akka Remote Reference Config File #
  3. #####################################
  4.  
  5. # This is the reference config file that contains all the default settings.
  6. # Make your edits/overrides in your application.conf.
  7.  
  8. # comments about akka.actor settings left out where they are already in akka-
  9. # actor.jar, because otherwise they would be repeated in config rendering.
  10.  
  11. akka {
  12.  
  13. actor {
  14.  
  15. serializers {
  16. akka-containers = "akka.remote.serialization.MessageContainerSerializer"
  17. proto = "akka.remote.serialization.ProtobufSerializer"
  18. daemon-create = "akka.remote.serialization.DaemonMsgCreateSerializer"
  19. }
  20.  
  21.  
  22. serialization-bindings {
  23. # Since com.google.protobuf.Message does not extend Serializable but
  24. # GeneratedMessage does, need to use the more specific one here in order
  25. # to avoid ambiguity
  26. "akka.actor.SelectionPath" = akka-containers
  27. "com.google.protobuf.GeneratedMessage" = proto
  28. "akka.remote.DaemonMsgCreate" = daemon-create
  29. }
  30.  
  31. deployment {
  32.  
  33. default {
  34.  
  35. # if this is set to a valid remote address, the named actor will be
  36. # deployed at that node e.g. "akka://sys@host:port"
  37. remote = ""
  38.  
  39. target {
  40.  
  41. # A list of hostnames and ports for instantiating the children of a
  42. # router
  43. # The format should be on "akka://sys@host:port", where:
  44. # - sys is the remote actor system name
  45. # - hostname can be either hostname or IP address the remote actor
  46. # should connect to
  47. # - port should be the port for the remote server on the other node
  48. # The number of actor instances to be spawned is still taken from the
  49. # nr-of-instances setting as for local routers; the instances will be
  50. # distributed round-robin among the given nodes.
  51. nodes = []
  52.  
  53. }
  54. }
  55. }
  56. }
  57.  
  58. remote {
  59.  
  60. ### General settings
  61.  
  62. # Timeout after which the startup of the remoting subsystem is considered
  63. # to be failed. Increase this value if your transport drivers (see the
  64. # enabled-transports section) need longer time to be loaded.
  65. startup-timeout = 10 s
  66.  
  67. # Timout after which the graceful shutdown of the remoting subsystem is
  68. # considered to be failed. After the timeout the remoting system is
  69. # forcefully shut down. Increase this value if your transport drivers
  70. # (see the enabled-transports section) need longer time to stop properly.
  71. shutdown-timeout = 10 s
  72.  
  73. # Before shutting down the drivers, the remoting subsystem attempts to flush
  74. # all pending writes. This setting controls the maximum time the remoting is
  75. # willing to wait before moving on to shut down the drivers.
  76. flush-wait-on-shutdown = 2 s
  77.  
  78. # Reuse inbound connections for outbound messages
  79. use-passive-connections = on
  80.  
  81. # Controls the backoff interval after a refused write is reattempted.
  82. # (Transports may refuse writes if their internal buffer is full)
  83. backoff-interval = 0.01 s
  84.  
  85. # Acknowledgment timeout of management commands sent to the transport stack.
  86. command-ack-timeout = 30 s
  87.  
  88. # If set to a nonempty string remoting will use the given dispatcher for
  89. # its internal actors otherwise the default dispatcher is used. Please note
  90. # that since remoting can load arbitrary 3rd party drivers (see
  91. # "enabled-transport" and "adapters" entries) it is not guaranteed that
  92. # every module will respect this setting.
  93. use-dispatcher = ""
  94.  
  95. ### Security settings
  96.  
  97. # Enable untrusted mode for full security of server managed actors, prevents
  98. # system messages to be send by clients, e.g. messages like 'Create',
  99. # 'Suspend', 'Resume', 'Terminate', 'Supervise', 'Link' etc.
  100. untrusted-mode = off
  101.  
  102. # Should the remote server require that its peers share the same
  103. # secure-cookie (defined in the 'remote' section)? Secure cookies are passed
  104. # between during the initial handshake. Connections are refused if the initial
  105. # message contains a mismatching cookie or the cookie is missing.
  106. require-cookie = off
  107.  
  108. # Generate your own with the script availbale in
  109. # '$AKKA_HOME/scripts/generate_config_with_secure_cookie.sh' or using
  110. # 'akka.util.Crypt.generateSecureCookie'
  111. secure-cookie = ""
  112.  
  113. ### Logging
  114.  
  115. # If this is "on", Akka will log all inbound messages at DEBUG level,
  116. # if off then they are not logged
  117. log-received-messages = off
  118.  
  119. # If this is "on", Akka will log all outbound messages at DEBUG level,
  120. # if off then they are not logged
  121. log-sent-messages = off
  122.  
  123. # Sets the log granularity level at which Akka logs remoting events. This setting
  124. # can take the values OFF, ERROR, WARNING, INFO, DEBUG, or ON. For compatibility
  125. # reasons the setting "on" will default to "debug" level. Please note that the effective
  126. # logging level is still determined by the global logging level of the actor system:
  127. # for example debug level remoting events will be only logged if the system
  128. # is running with debug level logging.
  129. # Failures to deserialize received messages also fall under this flag.
  130. log-remote-lifecycle-events = on
  131.  
  132. # Logging of message types with payload size in bytes larger than
  133. # this value. Maximum detected size per message type is logged once,
  134. # with an increase threshold of 10%.
  135. # By default this feature is turned off. Activate it by setting the property to
  136. # a value in bytes, such as 1000b. Note that for all messages larger than this
  137. # limit there will be extra performance and scalability cost.
  138. log-frame-size-exceeding = off
  139.  
  140. ### Failure detection and recovery
  141.  
  142. # Settings for the Phi accrual failure detector (http://ddg.jaist.ac.jp/pub/HDY+04.pdf
  143. # [Hayashibara et al]) used by the remoting subsystem to detect failed
  144. # connections.
  145. transport-failure-detector {
  146.  
  147. # FQCN of the failure detector implementation.
  148. # It must implement akka.remote.FailureDetector and have
  149. # a public constructor with a com.typesafe.config.Config and
  150. # akka.actor.EventStream parameter.
  151. implementation-class = "akka.remote.PhiAccrualFailureDetector"
  152.  
  153. # How often keep-alive heartbeat messages should be sent to each connection.
  154. heartbeat-interval = 1 s
  155.  
  156. # Defines the failure detector threshold.
  157. # A low threshold is prone to generate many wrong suspicions but ensures
  158. # a quick detection in the event of a real crash. Conversely, a high
  159. # threshold generates fewer mistakes but needs more time to detect
  160. # actual crashes.
  161. threshold = 7.0
  162.  
  163. # Number of the samples of inter-heartbeat arrival times to adaptively
  164. # calculate the failure timeout for connections.
  165. max-sample-size = 100
  166.  
  167. # Minimum standard deviation to use for the normal distribution in
  168. # AccrualFailureDetector. Too low standard deviation might result in
  169. # too much sensitivity for sudden, but normal, deviations in heartbeat
  170. # inter arrival times.
  171. min-std-deviation = 100 ms
  172.  
  173. # Number of potentially lost/delayed heartbeats that will be
  174. # accepted before considering it to be an anomaly.
  175. # This margin is important to be able to survive sudden, occasional,
  176. # pauses in heartbeat arrivals, due to for example garbage collect or
  177. # network drop.
  178. acceptable-heartbeat-pause = 3 s
  179. }
  180.  
  181. # Settings for the Phi accrual failure detector (http://ddg.jaist.ac.jp/pub/HDY+04.pdf
  182. # [Hayashibara et al]) used for remote death watch.
  183. watch-failure-detector {
  184.  
  185. # FQCN of the failure detector implementation.
  186. # It must implement akka.remote.FailureDetector and have
  187. # a public constructor with a com.typesafe.config.Config and
  188. # akka.actor.EventStream parameter.
  189. implementation-class = "akka.remote.PhiAccrualFailureDetector"
  190.  
  191. # How often keep-alive heartbeat messages should be sent to each connection.
  192. heartbeat-interval = 1 s
  193.  
  194. # Defines the failure detector threshold.
  195. # A low threshold is prone to generate many wrong suspicions but ensures
  196. # a quick detection in the event of a real crash. Conversely, a high
  197. # threshold generates fewer mistakes but needs more time to detect
  198. # actual crashes.
  199. threshold = 10.0
  200.  
  201. # Number of the samples of inter-heartbeat arrival times to adaptively
  202. # calculate the failure timeout for connections.
  203. max-sample-size = 200
  204.  
  205. # Minimum standard deviation to use for the normal distribution in
  206. # AccrualFailureDetector. Too low standard deviation might result in
  207. # too much sensitivity for sudden, but normal, deviations in heartbeat
  208. # inter arrival times.
  209. min-std-deviation = 100 ms
  210.  
  211. # Number of potentially lost/delayed heartbeats that will be
  212. # accepted before considering it to be an anomaly.
  213. # This margin is important to be able to survive sudden, occasional,
  214. # pauses in heartbeat arrivals, due to for example garbage collect or
  215. # network drop.
  216. acceptable-heartbeat-pause = 4 s
  217.  
  218.  
  219. # How often to check for nodes marked as unreachable by the failure
  220. # detector
  221. unreachable-nodes-reaper-interval = 1s
  222.  
  223. # After the heartbeat request has been sent the first failure detection
  224. # will start after this period, even though no heartbeat mesage has
  225. # been received.
  226. expected-response-after = 3 s
  227.  
  228. }
  229.  
  230. # After failed to establish an outbound connection, the remoting will mark the
  231. # address as failed. This configuration option controls how much time should
  232. # be elapsed before reattempting a new connection. While the address is
  233. # gated, all messages sent to the address are delivered to dead-letters.
  234. # If this setting is 0, the remoting will always immediately reattempt
  235. # to establish a failed outbound connection and will buffer writes until
  236. # it succeeds.
  237. retry-gate-closed-for = 0 s
  238.  
  239. # If the retry gate function is disabled (see retry-gate-closed-for) the
  240. # remoting subsystem will always attempt to reestablish failed outbound
  241. # connections. The settings below together control the maximum number of
  242. # reattempts in a given time window. The number of reattempts during
  243. # a window of "retry-window" will be maximum "maximum-retries-in-window".
  244. retry-window = 60 s
  245. maximum-retries-in-window = 3
  246.  
  247. # The length of time to gate an address whose name lookup has failed
  248. # or has explicitly signalled that it will not accept connections
  249. # (remote system is shutting down or the requesting system is quarantined).
  250. # No connection attempts will be made to an address while it remains
  251. # gated. Any messages sent to a gated address will be directed to dead
  252. # letters instead. Name lookups are costly, and the time to recovery
  253. # is typically large, therefore this setting should be a value in the
  254. # order of seconds or minutes.
  255. gate-invalid-addresses-for = 60 s
  256.  
  257. # This settings controls how long a system will be quarantined after
  258. # catastrophic communication failures that result in the loss of system
  259. # messages. Quarantining prevents communication with the remote system
  260. # of a given UID. This function can be disabled by setting the value
  261. # to "off".
  262. quarantine-systems-for = 60s
  263.  
  264. # This setting defines the maximum number of unacknowledged system messages
  265. # allowed for a remote system. If this limit is reached the remote system is
  266. # declared to be dead and its UID marked as tainted.
  267. system-message-buffer-size = 1000
  268.  
  269. # This setting defines the maximum idle time after an individual
  270. # acknowledgement for system messages is sent. System message delivery
  271. # is guaranteed by explicit acknowledgement messages. These acks are
  272. # piggybacked on ordinary traffic messages. If no traffic is detected
  273. # during the time period configured here, the remoting will send out
  274. # an individual ack.
  275. system-message-ack-piggyback-timeout = 1 s
  276.  
  277. # This setting defines the time after messages that have not been
  278. # explicitly acknowledged or negatively acknowledged are resent.
  279. # Messages that were negatively acknowledged are always immediately
  280. # resent.
  281. resend-interval = 1 s
  282.  
  283. ### Transports and adapters
  284.  
  285. # List of the transport drivers that will be loaded by the remoting.
  286. # A list of fully qualified config paths must be provided where
  287. # the given configuration path contains a transport-class key
  288. # pointing to an implementation class of the Transport interface.
  289. # If multiple transports are provided, the address of the first
  290. # one will be used as a default address.
  291. enabled-transports = ["akka.remote.netty.tcp"]
  292.  
  293. # Transport drivers can be augmented with adapters by adding their
  294. # name to the applied-adapters setting in the configuration of a
  295. # transport. The available adapters should be configured in this
  296. # section by providing a name, and the fully qualified name of
  297. # their corresponding implementation. The class given here
  298. # must implement akka.akka.remote.transport.TransportAdapterProvider
  299. # and have public constructor without parameters.
  300. adapters {
  301. gremlin = "akka.remote.transport.FailureInjectorProvider"
  302. trttl = "akka.remote.transport.ThrottlerProvider"
  303. }
  304.  
  305. ### Default configuration for the Netty based transport drivers
  306.  
  307. netty.tcp {
  308. # The class given here must implement the akka.remote.transport.Transport
  309. # interface and offer a public constructor which takes two arguments:
  310. # 1) akka.actor.ExtendedActorSystem
  311. # 2) com.typesafe.config.Config
  312. transport-class = "akka.remote.transport.netty.NettyTransport"
  313.  
  314. # Transport drivers can be augmented with adapters by adding their
  315. # name to the applied-adapters list. The last adapter in the
  316. # list is the adapter immediately above the driver, while
  317. # the first one is the top of the stack below the standard
  318. # Akka protocol
  319. applied-adapters = []
  320.  
  321. transport-protocol = tcp
  322.  
  323. # The default remote server port clients should connect to.
  324. # Default is 2552 (AKKA), use 0 if you want a random available port
  325. # This port needs to be unique for each actor system on the same machine.
  326. port = 2552
  327.  
  328. # The hostname or ip to bind the remoting to,
  329. # InetAddress.getLocalHost.getHostAddress is used if empty
  330. hostname = ""
  331.  
  332. # Enables SSL support on this transport
  333. enable-ssl = false
  334.  
  335. # Sets the connectTimeoutMillis of all outbound connections,
  336. # i.e. how long a connect may take until it is timed out
  337. connection-timeout = 15 s
  338.  
  339. # If set to "<id.of.dispatcher>" then the specified dispatcher
  340. # will be used to accept inbound connections, and perform IO. If "" then
  341. # dedicated threads will be used.
  342. # Please note that the Netty driver only uses this configuration and does
  343. # not read the "akka.remote.use-dispatcher" entry. Instead it has to be
  344. # configured manually to point to the same dispatcher if needed.
  345. use-dispatcher-for-io = ""
  346.  
  347. # Sets the high water mark for the in and outbound sockets,
  348. # set to 0b for platform default
  349. write-buffer-high-water-mark = 0b
  350.  
  351. # Sets the low water mark for the in and outbound sockets,
  352. # set to 0b for platform default
  353. write-buffer-low-water-mark = 0b
  354.  
  355. # Sets the send buffer size of the Sockets,
  356. # set to 0b for platform default
  357. send-buffer-size = 256000b
  358.  
  359. # Sets the receive buffer size of the Sockets,
  360. # set to 0b for platform default
  361. receive-buffer-size = 256000b
  362.  
  363. # Maximum message size the transport will accept, but at least
  364. # 32000 bytes.
  365. # Please note that UDP does not support arbitrary large datagrams,
  366. # so this setting has to be chosen carefully when using UDP.
  367. # Both send-buffer-size and receive-buffer-size settings has to
  368. # be adjusted to be able to buffer messages of maximum size.
  369. maximum-frame-size = 128000b
  370.  
  371. # Sets the size of the connection backlog
  372. backlog = 4096
  373.  
  374. # Enables the TCP_NODELAY flag, i.e. disables Nagle’s algorithm
  375. tcp-nodelay = on
  376.  
  377. # Enables TCP Keepalive, subject to the O/S kernel’s configuration
  378. tcp-keepalive = on
  379.  
  380. # Enables SO_REUSEADDR, which determines when an ActorSystem can open
  381. # the specified listen port (the meaning differs between *nix and Windows)
  382. # Valid values are "on", "off" and "off-for-windows"
  383. # due to the following Windows bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4476378
  384. # "off-for-windows" of course means that it's "on" for all other platforms
  385. tcp-reuse-addr = off-for-windows
  386.  
  387. # Used to configure the number of I/O worker threads on server sockets
  388. server-socket-worker-pool {
  389. # Min number of threads to cap factor-based number to
  390. pool-size-min = 2
  391.  
  392. # The pool size factor is used to determine thread pool size
  393. # using the following formula: ceil(available processors * factor).
  394. # Resulting size is then bounded by the pool-size-min and
  395. # pool-size-max values.
  396. pool-size-factor = 1.0
  397.  
  398. # Max number of threads to cap factor-based number to
  399. pool-size-max = 2
  400. }
  401.  
  402. # Used to configure the number of I/O worker threads on client sockets
  403. client-socket-worker-pool {
  404. # Min number of threads to cap factor-based number to
  405. pool-size-min = 2
  406.  
  407. # The pool size factor is used to determine thread pool size
  408. # using the following formula: ceil(available processors * factor).
  409. # Resulting size is then bounded by the pool-size-min and
  410. # pool-size-max values.
  411. pool-size-factor = 1.0
  412.  
  413. # Max number of threads to cap factor-based number to
  414. pool-size-max = 2
  415. }
  416.  
  417.  
  418. }
  419.  
  420. netty.udp = ${akka.remote.netty.tcp}
  421. netty.udp {
  422. transport-protocol = udp
  423. }
  424.  
  425. netty.ssl = ${akka.remote.netty.tcp}
  426. netty.ssl = {
  427. # Enable SSL/TLS encryption.
  428. # This must be enabled on both the client and server to work.
  429. enable-ssl = true
  430.  
  431. security {
  432. # This is the Java Key Store used by the server connection
  433. key-store = "keystore"
  434.  
  435. # This password is used for decrypting the key store
  436. key-store-password = "changeme"
  437.  
  438. # This password is used for decrypting the key
  439. key-password = "changeme"
  440.  
  441. # This is the Java Key Store used by the client connection
  442. trust-store = "truststore"
  443.  
  444. # This password is used for decrypting the trust store
  445. trust-store-password = "changeme"
  446.  
  447. # Protocol to use for SSL encryption, choose from:
  448. # Java 6 & 7:
  449. # 'SSLv3', 'TLSv1'
  450. # Java 7:
  451. # 'TLSv1.1', 'TLSv1.2'
  452. protocol = "TLSv1"
  453.  
  454. # Example: ["TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA"]
  455. # You need to install the JCE Unlimited Strength Jurisdiction Policy
  456. # Files to use AES 256.
  457. # More info here:
  458. # http://docs.oracle.com/javase/7/docs/technotes/guides/security/SunProviders.html#SunJCEProvider
  459. enabled-algorithms = ["TLS_RSA_WITH_AES_128_CBC_SHA"]
  460.  
  461. # There are three options, in increasing order of security:
  462. # "" or SecureRandom => (default)
  463. # "SHA1PRNG" => Can be slow because of blocking issues on Linux
  464. # "AES128CounterSecureRNG" => fastest startup and based on AES encryption
  465. # algorithm
  466. # "AES256CounterSecureRNG"
  467. # The following use one of 3 possible seed sources, depending on
  468. # availability: /dev/random, random.org and SecureRandom (provided by Java)
  469. # "AES128CounterInetRNG"
  470. # "AES256CounterInetRNG" (Install JCE Unlimited Strength Jurisdiction
  471. # Policy Files first)
  472. # Setting a value here may require you to supply the appropriate cipher
  473. # suite (see enabled-algorithms section above)
  474. random-number-generator = ""
  475. }
  476. }
  477.  
  478. ### Default configuration for the failure injector transport adapter
  479.  
  480. gremlin {
  481. # Enable debug logging of the failure injector transport adapter
  482. debug = off
  483. }
  484.  
  485. }
  486.  
  487. }

Note

Setting properties like the listening IP and port number programmatically is best done by using something like the following:

  1. ConfigFactory.parseString("akka.remote.netty.tcp.hostname=\"1.2.3.4\"")
  2. .withFallback(ConfigFactory.load());