Akka

run with plain jars

C:\Users\user\IdeaProjects\Pi>java -cp lib\scala-library-2.11.8.jar;lib\akka-actor_2.11-2.4.17.jar;lib\config-1.3.0.jar;target\classes;. com.home.akka.Pi

note: ";" for windows separator and ":" for linux separator.

http://doc.akka.io/docs/akka/2.0.1/intro/getting-started-first-java.html

client

regular client

        system = ActorSystem.create("MyApplication123");
        actor = system.actorOf(new Props(JLookupActor.class));
        System.out.println("local is :" + actor.path() + " " + actor.isTerminated());

the above code will create a local ActorSystem, and the actor has address:

akka://MyApplication123/user/$a

if you define a name for the actor, it will be like:

        actor = system.actorOf(new Props(JLookupActor.class), "xyz");

the actor has address:

akka://MyApplication123/user/xyz

If you try to access a remote actor like:

remoteActor = system.actorFor("akka://CalculatorApplication@127.0.0.1:2558/user/simpleCalculator");

the remoteActor will be deadLetters as :

akka://MyApplication123/deadLetters

the reason is ActorSystem is not configured to support remote.

client that needs to access remote system

in order to support remote look up, the system needs to be configured specially:

String configText = 
            "akka { \n" +
            "  actor {\n" +
            "    provider = \"akka.remote.RemoteActorRefProvider\"\n" +
            "  }\n" +
            "}\n";

        Config config = ConfigFactory.parseString(configText);

        system = ActorSystem.create("MyApplication123", ConfigFactory.load(config));
       remoteActor = system.actorFor("akka://CalculatorApplication@127.0.0.1:2558/user/simpleCalculator");

please note the the usage of "MyApplication123" in ActorSystem.create("") . It is different from the remote actor's address "CalculatorApplication".
basically, it creates a local ActorSystem that supports remote access, ref as :

REMOTE: RemoteServerStarted@akka://MyApplication123@192.168.1.112:2552

In fact, the concept "client/server" doesn't have much any difference. I meant the above ActorSystem supports remote interface, thus it is accessible
from other computers if any (local)actor is registered in to this ActorSystem.

  • the remoteActor has the following path, which is exactly as our lookup parameter:
akka://CalculatorApplication@127.0.0.1:2558/user/simpleCalculator
  • If we create a local actor based on the above ActorSystem, it will also has path as :
akka://MyLocalApplication123/user/$a
  • In addition, in the above example, the ActorSystem is created on default port 2552. If you would like to change the default port, you can change config as :
        String text = 
            "akka { \n" +
            "  actor {\n" +
            "    provider = \"akka.remote.RemoteActorRefProvider\"\n" +
            "  }\n" +
            "\n" + 
            "  remote {\n"+
            "    transport = \"akka.remote.netty.NettyRemoteTransport\"\n"+
            "    netty {\n" +
            "      port = 2555\n"+
            "    }\n" +
            "  }\n"+
            "}\n";

        Config config = ConfigFactory.parseString(text);

        system = ActorSystem.create("MyApplication123", ConfigFactory.load(config));

server side.

as I said before, you should not differentiate client and server. Any ActorSystem uses akka.remote.RemoteActorRefProvider
will become a server.

        String text = 
            "akka { \n" +
            "  actor {\n" +
            "    provider = \"akka.remote.RemoteActorRefProvider\"\n" +
            "  }\n" +
            "\n" + 
            "  remote {\n"+
            "    transport = \"akka.remote.netty.NettyRemoteTransport\"\n"+
            "    netty {\n" +
            "      hostname = \"127.0.0.1\"\n"+
            "      port = 2558\n"+
            "    }\n" +
            "  }\n"+
            "}\n";

        Config config = ConfigFactory.parseString(text);        
        system = ActorSystem.create("CalculatorApplication", ConfigFactory.load(config));

        ActorRef actor = system.actorOf(
                new Props(JSimpleCalculatorActor.class), "simpleCalculator");

the ActorSystem is started as :

RemoteServerStarted@akka://CalculatorApplication@127.0.0.1:2558

and the actor has path :

akka://CalculatorApplication/user/simpleCalculator

remote deploy from client.

suppose we have another JAdvancedCalculatorActor.java. For remote deploy, that means we kicks the creation of Actor from client side and it results a real Actor is instantiated at remote server.
the local machine only has a proxy. real computing happens at remote server.

the JAdvancedCalculatorActor.java has to be included in the jar package of both client and server side.

the server has no code change for remote deployment besides include the new JAdvancedCalculatorActor.java file.

the remote deply can be config based or programmatic based.

config based.

    public void deployConfig() {
        String text = 
           "akka { \n" +
            "  actor {\n" +
            "    provider = \"akka.remote.RemoteActorRefProvider\"\n" +
            "    \n" +
            "    deployment {\n" +
            "      /advancedCalculator { \n" +
            "        remote = \"akka://CalculatorApplication@127.0.0.1:2558\"\n" +    // Notice here it uses a remote server's existing ActorSystem CalculatorApplication
            "      } \n" +
            "   } \n" +        
            "  }\n" +
            "}\n";

        Config config = ConfigFactory.parseString(text);

        system = ActorSystem.create("MyApplication123", ConfigFactory.load(config));
        remoteActor = system.actorOf(new Props(JAdvancedCalculatorActor.class), "advancedCalculator");
    }

the above code line "remoteActor= system.actorOf(…) " will generate the following line

[CreationApplication-akka.actor.default-dispatcher-1] [ActorSystem(CreationApplication)] REMOTE: RemoteClientStarted@akka://CalculatorApplication@127.0.0.1:2558

notice the word: RemoteClientStarted. and the remoteActor has a physical path:

akka://CalculatorApplication@127.0.0.1:2558/remote/MyApplication123@192.168.1.112:2552/user/advancedCalculator

the above remoteActor also has a logical actor path in client machine

akka://MyApplication123@192.168.1.112:2552/user/advancedCalculator

for details. refer : http://doc.akka.io/docs/akka/2.0/general/addressing.html

please also notice the difference between system.actorOf(…) and system.actorFor(…) . the formal creates an Actor, the later only looks up an Actor.

programmatic remote deploy

        String text = 
            "akka { \n" +
            "  actor {\n" +
            "    provider = \"akka.remote.RemoteActorRefProvider\"\n" +
            "  }\n" +
            "}\n";

        Config config = ConfigFactory.parseString(text);        
        system = ActorSystem.create("MyApplication123", ConfigFactory.load(config));

        // notice this line the parameter "CalculatorApplication" matches server's existing ActorSystem.
        Address addr = new Address("akka", "CalculatorApplication", "127.0.0.1", 2558);    

        remoteActor = system.actorOf(
            new Props(JAdvancedCalculatorActor.class)
                    .withDeploy(new Deploy(new RemoteScope(addr))), "advancedCalculator");

misc

in the above , i mentioned that " the JAdvancedCalculatorActor.java has to be included in the jar package of both client and server side." in fact, the JAdvancedCalculatorActor.java
class's content doesn't need to identical. same function signature will be enough, like :

client side :

public class JAdvancedCalculatorActor extends UntypedActor {
    @Override
    public void onReceive(Object message) {
        System.out.println("received :" + message);
        getSender().tell("hello " + message.toString());

    }
}

server side:

public class JAdvancedCalculatorActor extends UntypedActor {
    @Override
    public void onReceive(Object message) {
        System.out.println("received1234 :" + message);
        getSender().tell("hello1234 " + message.toString());

    }
}

As real computing is done in server side, so the server side's output will be dumped to client's console.

Add a New Comment
or Sign in as Wikidot user
(will not be published)
- +
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License