2013-02-10 2 views
3

저는 Akka 2.1의 원격 액터에 대해 배우기 때문에 counter example provided by Typesafe을 적용하려고했습니다. 콘솔에서 틱을 보내기 위해 quick'n'dirty UI를 구현했습니다. 그리고 현재 카운트를 묻고 (그리고 결과를 보여주는 것으로) 종료합니다.Akka 2.1 원격 : 시스템에서 배우 공유

아이디어는 카운터 액터를 실행할 마스터 노드와 원격을 통해 메시지를 보낼 클라이언트 노드를 시작하는 것입니다. 그러나 구성 및 최소한의 코드 변경을 통해이를 달성하고 싶습니다. 따라서 구성을 변경하여 로컬 액터를 사용할 수 있습니다.

많은 인스턴스가 실행 중이지만 모든 API 호출이 하나의 액터를 통과해야하는 유사한 문제에 대해 this blog entry이 발견되었습니다.

비슷한 구성을 작성했지만 제대로 작동하지 않습니다. 현재 코드는 리모팅을 사용하지만 각각의 새 노드에 대해 마스터에 새 액터를 만들고이를 명시 적으로 경로에 제공하지 않고 기존 액터에 연결할 수 없습니다 (구성 지점 무시). 그러나 이것은 JVM간에 상태를 공유 할 수 없기 때문에 내가 원하는 것이 아닙니다. through a git repo

사용할 수

전체 실행 가능한 코드 이것은 내가 sbt run을 사용하고 다른 창 sbt run -Dakka.remote.netty.port=0에서 실행하는

import akka.actor._ 
import akka.pattern.ask 
import scala.concurrent.duration._ 
import akka.util.Timeout 
import scala.util._ 

case object Tick 
case object Get 

class Counter extends Actor { 
    var count = 0 

    val id = math.random.toString.substring(2) 
    println(s"\nmy name is $id\ni'm at ${self.path}\n") 
    def log(s: String) = println(s"$id: $s") 

    def receive = { 
    case Tick => 
     count += 1 
     log(s"got a tick, now at $count") 
    case Get => 
     sender ! count 
     log(s"asked for count, replied with $count") 
    } 
} 

object AkkaProjectInScala extends App { 
    val system = ActorSystem("ticker") 
    implicit val ec = system.dispatcher 

    val counter = system.actorOf(Props[Counter], "counter") 

    def step { 
    print("tick or quit? ") 
    readLine() match { 
     case "tick" => counter ! Tick 
     case "quit" => return 
     case _ => 
    } 
    step 
    } 
    step 

    implicit val timeout = Timeout(5.seconds) 

    val f = counter ? Get 
    f onComplete { 
    case Failure(e) => throw e 
    case Success(count) => println("Count is " + count) 
    } 

    system.shutdown() 
} 

내 config 파일

akka { 
    actor { 
     provider = "akka.remote.RemoteActorRefProvider" 
     deployment { 
      /counter { 
       remote = "akka://[email protected]:2552" 
      } 
     } 
    } 
    remote { 
     transport = "akka.remote.netty.NettyRemoteTransport" 
     log-sent-messages = on 
     netty { 
      hostname = "127.0.0.1" 
     } 
    } 
} 

그리고 전체 소스입니다.

답변

0

나는 git 프로젝트를 시도했지만 컴파일 에러를 제외하고 실제로는 잘 동작하며 run의 매개 변수가 아니라 jvm에 -Dakka.remote.netty.port=0 매개 변수로 sbt 세션을 시작해야한다.

또한 두 프로세스에서 카운터 액터를 시작할 필요가 없음을 이해해야합니다. 이 예제에서는 클라이언트에서 생성하여 서버 (포트 2552)에 배포하려고합니다. 서버에서 시작할 필요가 없습니다. 이 예제에서는 서버에 액터 시스템을 만드는 것으로 충분합니다.

+0

코드가 수정되었습니다. 매개 변수를 변경해도 동작은 변경되지 않습니다. 그것은 작동하지만 내가 원하는 방식으로 작동하지는 않습니다. 내 질문을 바꾸려면 : (가능한 경우) 모든 클라이언트에 대해 새 액터를 만들지 않고 기존 액터를 공유하도록 akka를 구성하는 방법은 무엇입니까? – edofic

1

나는 어떤 종류의 패턴을 사용할 수 있음을 알았습니다. Akka 리모컨은 원격 시스템에 배포 할 때만 사용할 수 있습니다 (구성을 통해 원격으로 볼 수있는 방법을 찾을 수 없습니다. 여기에 착각하니?).

따라서 ActorRef를 전달할 "스카우트"를 배포 할 수 있습니다. 지점 "scout-hack"아래 원래의 repo에서 실행 가능한 코드. 이것은 해킹처럼 느껴지기 때문입니다. 나는 여전히 구성 기반 솔루션을 고맙게 생각합니다.

배우

case object Fetch 

class Scout extends Actor{ 
    def receive = { 
    case Fetch => sender ! AkkaProjectInScala._counter 
    } 
} 

카운터 액터 작성은

lazy val _counter = system.actorOf(Props[Counter], "counter") 

그래서 단지 (포트에 의해 결정), 마스터에서 실행이

val counter: ActorRef = { 
    val scout = system.actorOf(Props[Scout], "scout") 
    val ref = Await.result(scout ? Fetch, timeout.duration) match { 
    case r: ActorRef => r 
    } 
    scout ! PoisonPill 
    ref 
} 
같이 꺼낼 수 지금 게으름

전체 구성

akka { 
    actor { 
     provider = "akka.remote.RemoteActorRefProvider" 
     deployment { 
      /scout { 
       remote = "akka://[email protected]:2552" 
      } 
     } 
    } 
    remote { 
     transport = "akka.remote.netty.NettyRemoteTransport" 
     log-sent-messages = on 
     netty { 
      hostname = "127.0.0.1" 
     } 
    } 
} 

EDIT : 나는 또한 "counterPath"에 대한 구성을 확인하십시오. anf if actorFor (path) else actor를 작성하십시오. 니스와 당신은 주인을 주사 할 수 있습니다. 그리고 코드는 "스카우트"보다 훨씬 깨끗하지만, 여전히 날씨를 보거나 배우를 생성해야합니다. 나는 이것이 피할 수없는 것 같아요.

관련 문제