19563

Akka actors scaling across JVM's and servers, and example at akka.io

Question:

I find the introductory <a href="http://akka.io/" rel="nofollow">example of Akka remoting supplied on the Akka landing page</a> a bit hard to swallow as an introduction, and the length of documentation necessary for learning the ins and outs of remoting malstructured for introductory purposes.

Here below is the code from the mentioned example, and I'd like to ask for a delineation of what that code means with some fair context, while relating to the question of whether any actor can be messaged remotely as if it were local requiring only a mere change of configuration. Previous answers about <a href="https://stackoverflow.com/questions/7320866/akka-actor-vs-remote-actor" rel="nofollow">this last bit</a> may seem somewhat contradictory to current Akka documentation, whereas the documentation in itself is somewhat inconclusive about this very point.

// ------------------------------ // config on all machines akka { actor { provider = akka.remote.RemoteActorRefProvider deployment { /greeter { remote = akka.tcp://MySystem@machine1:2552 } } } } // ------------------------------ // define the greeting actor and the greeting message case class Greeting(who: String) extends Serializable class GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) ⇒ log.info("Hello " + who) } } // ------------------------------ // on machine 1: empty system, target for deployment from machine 2 val system = ActorSystem("MySystem") // ------------------------------ // on machine 2: Remote Deployment - deploying on machine1 val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter") // ------------------------------ // on machine 3: Remote Lookup (logical home of “greeter” is machine2, remote deployment is transparent) val system = ActorSystem("MySystem") val greeter = system.actorSelection("akka.tcp://MySystem@machine2:2552/user/greeter") greeter ! Greeting("Sonny Rollins")

So an introductory explanation of this example code that also takes care of the key aspects mentioned above would be very helpful. An explanation that should hopefully enable picking an actors architecture that can easily scale within a single JVM and across JVM's and server boundaries, rather than going into experimentation mode for days if not more.

Thanks!

Answer1:

Its probably easiest to explain the example you posted from bottom to top. At the end it shows vanilla location transparency to get an actor ref where we wouldn't hardcode the location string. With that minor modification we get:

// ------------------------------ // on machine 3: Remote Lookup (logical home of “greeter” is machine2, remote deployment is transparent) val system = ActorSystem("MySystem") val greeter = system.actorSelection(uri) // where uri is from config or some directory greeter ! Greeting("Sonny Rollins")

How to lookup the location of an actor from configuration is shown at <a href="https://stackoverflow.com/questions/9125142/can-a-lookup-an-akka-actor-address-from-configuration?rq=1" rel="nofollow">can a lookup an akka actor address from configuration?</a> which sums up location transparency of using an actor. Once you have the ActorRef from the selection by uri you don't need to know whether its a local or a remote actor you can just message it.

Moving up the example the bit where it says:

// ------------------------------ // on machine 2: Remote Deployment - deploying on machine1 val system = ActorSystem("MySystem") val greeter = system.actorOf(Props[GreetingActor], name = "greeter")

this is there to demonstrate local transparency of deploying an actor. The actorOf is a factory instantiation rather than a lookup hence it is a deployment. The name property deploys it to a uri path of "/user/greeter". If you had a single jvm configuration (e.g. empty configuration) and ran that in a single process you would get an local actor deployed into the single jvm. Yet the example comment says its running on machine2 and deploying into machine1; this is because of the config at each jvm which is further up the file:

akka { actor { provider = akka.remote.RemoteActorRefProvider deployment { /greeter { remote = akka.tcp://MySystem@machine1:2552 } } } }

That is saying that the user space "/user/greeter" is going to use RemoteActorRefProvider to remote deploy onto the actor system MySystem on machine1. If you took out that config then the sample code to deploy would not remote deploy but would local deploy. If it was a local deploy you could look it up using a local path without the full uri pointing to the system it is actually deployed onto. Regardless of whether its a local or remote deploy you get an ActorRef and message it.

Moving up the file some more at:

// ------------------------------ // on machine 1: empty system, target for deployment from machine 2 val system = ActorSystem("MySystem")

that is simply telling you that if you have config which will remote deploy actors at location "greeter" into "MySystem" on machine1 then you should start an actor system on machine1 with a name which matches the config. If not you will get connection or lookup errors trying to deploy or resolve "greeter" from other machines.

Finally the actor itself is location transparent as it has nothing about location baked into it as shown by:

// ------------------------------ // define the greeting actor and the greeting message case class Greeting(who: String) extends Serializable class GreetingActor extends Actor with ActorLogging { def receive = { case Greeting(who) ⇒ log.info("Hello " + who) } }

So that actor has no idea whether it is a local actor or a remote actor or is running in a unit test using the akka Testkit. Effectively the configuration file shown deployed in all the machines is modifying the factory behaviours of the actor systems to deploy into the location "greeter" into one machine.

Recommend

  • Angular 1.3 breaking changes - scope set but reset before $apply
  • What's the difference between Handlebars helpers and Ember Handlebars helpers?
  • Using Vue.js in Laravel 5.3
  • How extend behaviour of super actor in akka
  • Reading external plain text content into string
  • Spring Boot MVC not using model values in JSP
  • Convert a statement with adjective in RDF triple
  • How to press a key programmatically in a TextField?
  • Can I extend actor in use case? [closed]
  • Google AppEngine Python Web upload file and read the content
  • Facebook Error (#200) The user hasn't authorized the application to perform this action
  • Akka clustering - force actors to stay on specific machines
  • When testing Spray services with Scalatest, how to introduce implicit values?
  • Should actors/services be split into multiple projects?
  • How tin-can-api works offline?
  • Akka Scala actor scheduled message does not appear to fire
  • Whoops! Lost connection to undefined - Connection Lost Just After The Connection Established
  • iTextSharp - Copying elements from one PDF to another
  • Akka Scheduler throws exceptions only in MicroKernel but works fine in eclipse IDE for scala
  • Stuck on parsing a JSON response to a Java Object in Android
  • How to exclude transitive dependency in Sbt ( in context of assembly plugin )?
  • Exclude field from a form in JSF
  • Pros and cons in using multiple actor types in same Service Fabric service
  • named parameter to npm run script
  • How to use a huge typescript library without polluting html?
  • In Akka Java actor model, can a router create actors with non-default constructor?
  • Entity Framework Core: Include many-to-many related objects in WebAPI
  • Java : Simple XML not parsing the xml. Gives Exception
  • In Akka, is ActorContext thread safe?
  • Spray.io: When (not) to use non-blocking route handling?
  • How to set my toolbar fixed while scrolling android
  • AT Commands to Send SMS not working in Windows 8.1
  • Cannot Parse HTML Data Using Android / JSOUP
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Java static initializers and reflection
  • apache spark aggregate function using min value
  • unknown Exception android
  • Sorting a 2D array using the second column C++
  • Observable and ngFor in Angular 2
  • Unable to use reactive element in my shiny app