2011-10-07 108 views
4

我嘗試從斯卡拉演員向阿卡演員發送「Ping」和「Pong」端口this simple actor example,但我不斷收到錯誤,根本錯誤。將簡單的斯卡拉遠程演員示例移植到阿卡演員

考慮以下代碼:

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) 

的想法是,我開始了兩個應用程序,PingPong它試圖將消息發送到對方每秒鐘並在終端上打印(如果在兩秒鐘內沒有收到任何消息,則打印一條錯誤消息)。

+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

我是否需要實現「等待並重試,直到其他演員出現」 - 在Scala演員之內或在演員之外進行演示? – soc

+0

那麼,這真的取決於你,你想如何設計的東西。關鍵是PingActor必須能夠獲得對遠程PongActor的初始引用,因此如果將重試邏輯放在actor外部,則需要將引用傳遞給PingActor。這可以通過消息輕鬆完成。 –

+0

@soc爲你做了這項工作嗎? –