2011-10-07 4 views
4

"Ping"및 "Pong"을 스칼라 액터에서 Akka 액터로 전송하는 포트 this simple actor example을 계속 시도하지만 오류가 계속 발생하며 단순한 오류인지 또는 일부 오류인지 궁금합니다. 근본적인 잘못.간단한 스칼라 원격 액터 예제를 Akka 액터로 이식합니다

import akka.actor.Actor._ 
import akka.actor.Actor 

case class Message(text: String) 

class PingPongActor(name: String) extends Actor { 

    def receive = { 
     case Message(msg) => 
     println("received: " + msg) 
     Thread.sleep(1000) 
     self.reply(Message("Ping")) 
     case None => println("ping: timed out!") 
    } 
} 

object Ping extends App { 
    remote.start("localhost", 2552) 
     .register("ping-service", actorOf(new PingPongActor("pong"))) 

    val actor = remote.actorFor("ping-service", "localhost", 2552) 

    actor ! (Message("Ping")) 
} 

object Pong extends App { 
    remote.start("localhost", 2553) 
     .register("pong-service", actorOf(new PingPongActor("ping"))) 

    val actor = remote.actorFor("pong-service", "localhost", 2553) 

    actor ! (Message("Pong")) 
} 

나는이 오류가 계속 :

이 코드 고려 나는이 응용 프로그램을 시작하는 것이

received: Ping 
[GENERIC] [07.10.11 23:18] [RemoteServerStarted([email protected])] 
[ERROR] [07.10.11 23:18] [akka:event-driven:dispatcher:global-2] [LocalActorRef] 
    No sender in scope, can't reply. 
    You have probably: 
     1. Sent a message to an Actor from an instance that is NOT an Actor. 
     2. Invoked a method on an TypedActor from an instance NOT an TypedActor. 
    You may want to have a look at safe_! for a variant returning a Boolean 
akka.actor.IllegalActorStateException: 
    No sender in scope, can't reply. 
    You have probably: 
     1. Sent a message to an Actor from an instance that is NOT an Actor. 
     2. Invoked a method on an TypedActor from an instance NOT an TypedActor. 
    You may want to have a look at safe_! for a variant returning a Boolean 
[laptop_e3263500-f129-11e0-a78d-001636ff8076] 
    at akka.actor.NullChannel$.$bang(Channel.scala:177) 
    at akka.actor.ActorRef$class.reply(ActorRef.scala:398) 
    at akka.actor.LocalActorRef.reply(ActorRef.scala:605) 
    at PingPongActor$$anonfun$receive$1.apply(RemoteActor.scala:21) 
    at PingPongActor$$anonfun$receive$1.apply(RemoteActor.scala:15) 
    at akka.actor.Actor$class.apply(Actor.scala:545) 
    at PingPongActor.apply(RemoteActor.scala:13) 

아이디어입니다 Ping 서로에게 메시지를 보내려고 Pong 매초마다 인쇄하여 터미널에 인쇄하십시오 (또는 2 초 동안 아무런 메시지도 수신되지 않으면 오류 메시지를 인쇄하십시오).

+1

음 ... 오류 메시지는 액터가 아닌 인스턴스에서 액터로 메시지를 보냈다 고 말합니다. 당신은 원격 측면에 대해 걱정하기 전에 먼저 그것을 고칠 필요가 없습니까? –

답변

6

코드의 가장 큰 근본적인 문제는 배우 외부에서 메시지를 보내고 있으므로 응답이없는 곳입니다. 최초의 예에서, Message("ping")Ping 액터의 act() 루프 내에서 전송됩니다. 하지만 실제로는 몇 가지 문제가 있으며 코드를 약간 재구성하여 다시 시작하는 것이 좋습니다. 다음은 작동하는 예제이지만 특정 순서로 클라이언트를 시작하는 방법에 따라 다릅니다. 물론 PingActor에서 연결을 다시 시도하기 위해 다시 작성할 수 있습니다.

sealed trait Message 
case class Ping extends Message 
case class Pong extends Message 

class PingActor extends Actor { 

    override def preStart = { 
    val pong = remote.actorFor("pong-service", "localhost", 2553) 
    pong ! Ping 
    } 

    def receive = { 
    case Pong => { 
     println("Received pong") 
     Thread.sleep(1000) 
     self.reply(Ping) 
    } 
    } 
} 

class PongActor extends Actor { 
    def receive = { 
    case Ping => { 
     println("Received ping") 
     Thread.sleep(1000) 
     self.reply(Pong) 
    } 
    } 
} 

object pingApp extends App { 
    val actor = actorOf(new PingActor) 
    remote.start("localhost", 2552) 
     .register("ping-service", actor) 
} 

object pongApp extends App { 
    val actor = actorOf(new PongActor) 
    remote.start("localhost", 2553) 
     .register("pong-service", actor) 
} 
+0

"다른 배우가 올 때까지 기다렸다가 다시 시도"할 필요가 있습니까? 스칼라 액터와 같이 배우 내부에서 루프를 돌릴 수 있습니까? – soc

+0

글쎄, 그건 당신에게 달려 있고, 어떻게 디자인하고 싶은지. 핵심은 PingActor가 원격 PongActor에 대한 초기 참조를 가져올 수 있어야하므로, 재시도 논리를 액터 외부에두면 PingActor에 대한 참조를 전달해야합니다. 이것은 쉽게 메시지를 통해 이루어질 수 있습니다. –

+0

@soc이 (가) 당신을 위해이 작업을 했습니까? –

관련 문제