Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to create remote actors dynamically and control them by using AKKA

what I want to do is:

1) create a master actor on a server which can dynamically create 10 remote actors on 10 different machine

2) master actor distribute the task to 10 remote actors

3) when every remote actor finish their work, they send the results to the master actor

4) master actor shut down the whole system

my problems are:

1) I am not sure how to config the master actor and below is my server part code:

class MasterAppliation extends Bootable{
    val hostname = InetAddress.getLocalHost.getHostName
    val config = ConfigFactory.parseString(
          s"""
            akka{
            actor{
                provider = "akka.remote.RemoteActorRefProvider"
                deployment {
                    /remotemaster {
                        router = "round-robin"
                        nr-of-instances = 10
                        target {
                            nodes = ["akka.tcp://remotesys@host1:2552", "akka.tcp://remotesys@host2:2552", ....... akka.tcp://remotesys@host10:2552"]
                        }
                }
            }
            remote{
                enabled-transports = ["akka.remote.netty.tcp"]
                netty.tcp{
                hostname = "$hostname"
                port = 2552
                }
            }     
          }""")

    val system = ActorSystem("master", ConfigFactory.load(config))        
    val master = system.actorOf(Props(new master), name = "master") 
    def dosomething = master ! Begin()
    def startup() {}
    def shutdown() {
        system.shutdown()
    }
}

class master extends Actor {   
   val addresses = for(i <- 1 to 10) 
       yield AddressFromURIString(s"akka://remostsys@host$i:2552")

   val routerRemote = context.actorOf(Props[RemoteMaster].withRouter(
           RemoteRouterConfig(RoundRobinRouter(12), addresses)))

   def receive = {
     case Begin=>{
       for(i <- 1 to 10) routerRemote ! Work(.....)     
     }
     case Result(root) ........      
   }
}


object project1 {
  def main(args: Array[String]) {                
    new MasterAppliation
  }
}

2) I do not know how to create a remote actor on remote client. I read this tutorial. Do I need to write the client part similar to the server part, which means I need create an object which is responsible to create a remote actor? But that also means when I run the client part, the remote actor is already created ! I am really confused.

3) I do not how to shut down the whole system. In the above tutorial, I find there is a function named shutdown(), but I never see anyone call it.

This is my first time to write a distributed program in Scala and AKKA. So I really need your help. Thanks a lot.

like image 202
city Avatar asked Sep 14 '13 05:09

city


1 Answers

Setting up the whole thing for the first time is a pain but if you do it once you will have a good skeleton that you will user on regular basis.

I've written in comment below the question user clustering not remoting.

Here is how I do it: I set up an sbt root project with three sub-projects.

  • common
  • frontend
  • backend

In common you put everything that is common to both projects e.g. the messages that they share, actor classes that are created in frontend and deployed to backend.

Put a reference.conf to common project, here is mine:

akka {
loglevel = INFO
actor {
    provider = "akka.cluster.ClusterActorRefProvider"
    debug {
        lifecycle = on
    }
}

 cluster {
      seed-nodes = [
        "akka.tcp://[email protected]:2558",
        "akka.tcp://[email protected]:2559"
      ]
  }

}

Now in the frontend:

akka {


    remote {
        log-remote-lifecycle-events = off
        netty.tcp {
            hostname = "127.0.0.1"
            port = 2558
        }
    }

    cluster {
      auto-down = on
      roles = [frontend]
    }
}

and the backend

akka {

    remote {
        log-remote-lifecycle-events = off
        netty.tcp {
            hostname = "127.0.0.1"
            port = 0
        }
    }

    cluster {
      auto-down = on
      roles = [backend]
    }
}

This will work like this: You start the fronted part first which will control the cluster. Then you can start any number of backends you want that will join automatically (look at the port, it's 0 so it will be chosen randomly).

Now you need to add the whole logic to the frontend main: Create the actor system with name application:

val system = ActorSystem("application")

Do the same at the backend main.

Now write your code in fronted so it will create your workers with a router, here's my example code:

context.actorOf(ServiceRuntimeActor.props(serviceName)
        .withRouter(
          ClusterRouterConfig(ConsistentHashingRouter(),
            ClusterRouterSettings(
              totalInstances = 10, maxInstancesPerNode = 3,
            allowLocalRoutees = false, useRole = Some("backend"))
          )
        ),
        name = shortServiceName)

just change your ServiceRuntimeActor to name of your worker. It will deploy workers to all backends that you've started and limit this to max 3 per node and max 10 in total.

Hope this will help.

like image 172
almendar Avatar answered Sep 22 '22 05:09

almendar