관리 메뉴

HAMA 블로그

[Play2] Remote Akka 연결하기 (번역) 본문

PlayFramework2

[Play2] Remote Akka 연결하기 (번역)

[하마] 이승현 (wowlsh93@gmail.com) 2016. 10. 10. 21:04


Play Framework - 원격 Akka 액터에 연결하기

원본 : http://qiita.com/visualskyrim/items/350ba0112cd9a95388ff

참고:


디펜던시 추가 

build.sbt 에  Akka 원격 라이브러리를 추가한다. 

libraryDependencies ++= Seq(
  // ... other libs
  "com.typesafe.akka" %% "akka-remote" % "2.3.4"
)

Akka 설정 조정 

For API 

Play API 를 위해서 conf/application.conf 에 있는 디폴트 Akka 세팅을 다음과 같이 변경 한다.

akka {
  actor {
    provider = "akka.remote.RemoteActorRefProvider" # offer the provider
  }

  remote {
    enabled-transports = ["akka.remote.netty.tcp"] # enable protocol
    netty.tcp {
      hostname = "127.0.0.1" # your host
      port = 2553 # port
    }
  }
}

만약 설정 파일에 아카 오브젝트가 없다면, 설정파일에 그냥 추가하라.

For Actor

위에서 했던 것과 비슷한 설정을src/main/resources/application.conf에 하라.

yourSystem { # the name your actor system is going to use
  akka { 
    # other thing is just the same as that in API
    loglevel = "DEBUG"
    loggers = ["akka.event.slf4j.Slf4jLogger"]

    actor {
      provider = "akka.remote.RemoteActorRefProvider"

      default-dispatcher {
      }
    }

    remote {
      enabled-transports = ["akka.remote.netty.tcp"]
      netty.tcp {
        hostname = "127.0.0.1"
        port = 2552 # Note if you are running API and Actor program in localhost, make sure they are not using the same port
      }
    }
  }
}

 그리고나서 코드에 이 세팅을 적용하라.

// ... some codes for launch the program val system = ActorSystem("CoolSystem", config.getConfig("yourSystem"))

Note 위의 provider 를 해당 아카 버전으로  주의 있게 바꾸고 올바른 프로바이더를 선택하라.

Program

API

자바를 이용해서 플레이를 사용할 것이다. 스칼라에 대한 것은 여기를 봐라.  this.

컨트롤러안에서 리모트 액터로 연결한다.  아래 코드 참고 :

public static F.Promise<Result> askYourActorSomething(final String info) { String actorPath = actorHelper.getPath(); // get akka path of your worker, this will not show in my example ActorSelection actor = Akka.system().actorSelection(actorPath); return play.libs.F.Promise.wrap(ask(actor, new MessageToActor(info), 5000)).map( // use ask pattern so that we can get sync response from actor; wrap into Promise new F.Function<Object, Result>() { // the callback when actor sends back response public Result apply(Object resp) { return ok((String) resp); } } ); }

여기서 주의깊게 봐야할 포인트는 만약 ask 패턴을 사용한다면 결과를 Promise 로 감싸야한다는점.

Actor

액터 코드:

class Worker extends Actor {
  override def receive = {
    case MessageToActor(info) => // get message from API
      sender ! "worked!" //  response to API
  }
}

런치 코드

// fetch configs
val remoteConfig = ConfigFactory.load.config.getConfig("yourSystem").getConfig("akka").getConfig("remote").getConfig("netty.tcp")
val actorHost = remoteConfig.getString("hostname")
val actorPort = remoteConfig.getInt("port")
val workerName = "worker"

val actorPath = "akka.tcp://" + "yourSystem" + "@" + actorHost + ":" + actorPort + "/user/" + workerName
println(actorPath) // here you know what your actor's path is, well, just for show, don't do this sort of thing your code.
val system = ActorSystem("CoolSystem",config.getConfig("yourSystem"))
val actor = system.actorOf((new Worker()), name = workerName)

이제 만약 컨트롤러  askYourActorSomething  가 호출되면, 경로에 해당하는 당신의 액터에 메세지를 보낼 것이다. 그리고 나서 액터는 이 메세지를 받고 API 컨트롤러에게 다시 문자를 돌려 줄 것이다.  마지막으로 API  는 "worked!" 를 리턴 할 것 이다.

한 가지 더 ..

제품화된  플레이 어플리케이션에서 원격 액터를 사용할 예정이라면  , 특별히 분산 환경이라면 , 좀 더 해야할 것들이 생긴다..

방화벽

API 와 액터 프로그램이 서로 접근하지 못하게 할 것이다.

만약 EC2 를 사용한다면 security groups. 를 세팅해서 해결하라.  서로 다른 그룹의 인바운드에 있는지 확인해야한다. 



Comments