Actors in Java: Configuring Remote Systems
Remote systems cannot be ignored. They are the heart of actor programming. The ability of an actor application to smoothly scale out geographically is a tremendous advantage in meeting the challenges of growth. Today we will learn the basics of setting up for remote interaction between actors. If you wish to set up to try coding a set of remote actor systems and do not as yet have a development environment see either of the last two posts for directions.
Actor Paths and Actor References
In previous exercises we have exclusively used the class ActorRef to instantiate actor references that enable messaging between actors. This works for a local actor system but does not extend to remote actor systems. An actor reference is an object that refers to a living instance of an actor object. When an actor ceases to exist all actor references to it become invalid. An actor path is different. An actor path defines a way to send a message to an actor. The existence of an actor path says nothing about whether or not there is a live actor residing at the end of the path. An analog to an actor path is a land line telephone number to a service at a certain house address. You can call anytime. Someone may or may not be home to receive your call. But in either case the phone number is still valid. Actor paths are the same way. An understanding of actor paths is key to understanding both the configuration and application coding of remote actors systems.
Actor Paths in Detail
An actor path is implemented as an ordinary text string. An actor path may be absolute or relative. Here is an example absolute actor path specifying an IP address that is not in service.
Let's take this apart.
First we have "akka.tcp://". This is always “akka.” followed by the protocol to be used. This example specifies the use of the tcp transport driver for remote communication between actors. The tcp service is the default implementation of the akka.remote.transport.Transport interface as it comes shipped with the Akka distribution. It is possible to use other transport layer services such as udp to implement the transport interface. The reference.conf file of the remoting library, akka-remote.jar, contains a list of transport drivers that can be specified for use. Below is the setting that comes with the Akka distribution.
enabled-transports = ["akka.remote.netty.tcp"]
You can extend this list with other transports available on your host. Best practice would be to place your additional transport protocol specifications in your application.conf file.
Actor System Name
"ReactorSystem" specifies the name of the actor system that messages arriving at the host should be directed to. The actor being sent a message must be under the supervision of this actor system.
IP Address and Port
"192.0.2.10:4001" is the ip address of the host receiving the message and port registered by the actor system that supervises the actor being sent the message.
There are three scopes within every actor system, each of them supervised by a special actor called the guardian actor.
|root||The container of both subordinate scopes and indirectly of all actors within its actor system.|
|system||Child scope of root. Contains all of the special system service actors.|
|user||Child scope of root. This scope contains all of the ordinary application created actors.|
The scope "user " in the example actor path specifies that this is a path to a regular application actor.
"ReactorModel" in the example actor path specifies the name of the recipient actor being addressed. This actor name is given at actor creation time See how an actor named "ReactorModel'" is created in the examples below.
Create Actor From An Actor System
ActorRef myActor = system.actorOf(
new Props(ReactorModel.class), "ReactorModel");
Create Actor From A Parent Actor
ActorRef myActor = getContext().actorOf(
new Props(ReactorModel.class), "ReactorModel");
The Configuration File
Below is an example of a minimum remote configuration file. This is the application.conf file that you will put at the base of your application's classpath.
actor.provider = "akka.remote.RemoteActorRefProvider"
remote.transport = "akka.remote.netty.NettyRemoteTransport"
remote.netty.tcp.hostname = "192.0.2.10"
remote.netty.tcp.port = 4001
The only things that you really need to change here are the configuration name at the top, the hostname, and the port.
Gaining Addressability to a Remote Actor
An ActorSelection object is the remote counterpart to the local ActorRef object. Like the ActorRef object ( and unlike an actor path ) the ActorSelection object is only valid if the named actor is alive. The way ActorSelection is used is shown in the method invocation below.
The above uses a method call on an actor's context to construct an ActorSelection object. If the ActorSelection object returned is null then the actor named in the call is not alive or else there is something wrong in the address or protocol. If the ActorSelection object returned is not null it means the the actor named in the call is alive and well at the address given and can be sent messages.
Sending a Remote Message
To send a message to a remote actor you make use of the ActorSelection object. The snippet below shows how.
selection.tell( message, getSelf());
The code above executes the tell method with the message object, and the self address of the sending actor as arguments. That's all there is to it. Just fire and forget. An asynchronous communication is on its way to the recipient actor.
This and the previous post have presented a basic introduction to the dry but necessary topic of configuring an actor application. What is coming in the next post is a lot more fun. I will present the first part of a sequence of posts that deal with the development of an actor based surveillance and security system. This system does not secure stores of data. It is a surveillance and security system designed to protect physical premises such as offices, schools, shopping malls, etc. All application source will be made available for free download under the MIT license. Look for “Actors in Java: Coding the Surveillance and Security Application – Part 1” to be published on November 20, 2013.