2016-04-27 140 views
2

我是新的阿卡,我使用Akka 2.3.3版本創建演員。我將創建遠程角色並嘗試訪問客戶端。每當我要運行測試用例,下面的異常會拋出:Akka演員:遠程演員異常「期貨超時後」

[INFO] [04/27/2016 07:51:23.727] [Localsystem-akka.actor.default-dispatcher-3] [akka://Localsystem/deadLetters] Message [com.harmeetsingh13.chapter2.messages.SetRequest] from Actor[akka://Localsystem/temp/$a] to Actor[akka://Localsystem/deadLetters] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 
[INFO] [04/27/2016 07:51:23.745] [Localsystem-akka.actor.default-dispatcher-3] [akka://Localsystem/deadLetters] Message [com.harmeetsingh13.chapter2.messages.GetRequest] from Actor[akka://Localsystem/temp/$b] to Actor[akka://Localsystem/deadLetters] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 

Futures timed out after [10 seconds] 
java.util.concurrent.TimeoutException: Futures timed out after [10 seconds] 
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219) 
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223) 
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:190) 
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53) 
at scala.concurrent.Await$.result(package.scala:190) 
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply$mcV$sp(SClientIntegrationSpec.scala:18) 
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(SClientIntegrationSpec.scala:15) 
at com.harmeetsingh13.chapter2.SClientIntegrationSpec$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(SClientIntegrationSpec.scala:15) 
at org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:22) 
at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85) 
at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) 
at org.scalatest.Transformer.apply(Transformer.scala:22) 
at org.scalatest.Transformer.apply(Transformer.scala:20) 
at org.scalatest.FunSpecLike$$anon$1.apply(FunSpecLike.scala:422) 
at org.scalatest.Suite$class.withFixture(Suite.scala:1122) 
at com.harmeetsingh13.chapter2.SClientIntegrationSpec.withFixture(SClientIntegrationSpec.scala:11) 
at org.scalatest.FunSpecLike$class.invokeWithFixture$1(FunSpecLike.scala:419) 
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:431) 
at org.scalatest.FunSpecLike$$anonfun$runTest$1.apply(FunSpecLike.scala:431) 
at org.scalatest.SuperEngine.runTestImpl(Engine.scala:306) 
at org.scalatest.FunSpecLike$class.runTest(FunSpecLike.scala:431) 
at com.harmeetsingh13.chapter2.SClientIntegrationSpec.runTest(SClientIntegrationSpec.scala:11) 
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:464) 
at org.scalatest.FunSpecLike$$anonfun$runTests$1.apply(FunSpecLike.scala:464) 
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:413) 
at org.scalatest.SuperEngine$$anonfun$traverseSubNodes$1$1.apply(Engine.scala:401) 
............ 

下面我的服務器代碼: Main.scala

object Main extends App{ 


private val configFile = getClass.getClassLoader.getResource("application.conf").getFile; 
private val config = ConfigFactory.parseFile(new File(configFile)) 

val system = ActorSystem("SimpleClientServer", config) 
system.actorOf(Props[AkkadmeyDB], name = "akkademy-db") 
} 

application.conf:

akka{ 
actor{ 
    provider = "akka.remote.RemoteActorRefProvider" 
} 
remote{ 
enabled-transports = ["akka.remote.netty.tcp"] 
    netty.tcp { 
    hostname = "127.0.0.1" 
    port = 2552 
    } 
    log-sent-messages = on 
    log-received-messages = on 
} 
} 

AkkadmeyDB.scala演員等級:

class AkkadmeyDB extends Actor{ 

val map = new HashMap[String, Object] 
val log = Logging(context.system, this) 

override def receive: Receive = { 
    case SetRequest(key, value) => 
    log.info("received SetRequest - key: {} value: {}", key, value) 
    map.put(key, value) 
    sender() ! Status.Success 
    case GetRequest(key) => 
    log.info("received GetRequest - key: {}", key) 
    val response = map.get(key) 
    response match{ 
    case Some(x) => sender() ! x 
    case None => Status.Failure(new KeyNotFoundException(key)) 
    } 
    case o => Status.Failure(new ClassNotFoundException()) 
    } 
} 
0123如下

客戶端代碼: SClient.scala

class SClient(remoteIp: String) { 

    private implicit val timeout = Timeout(10 seconds) 
    private implicit val system = ActorSystem("Localsystem") 
    private val remoteAddress = s"akka.tcp://[email protected]$remoteIp/user/akkademy-db"; 
    private val remoteDb = system.actorSelection(remoteAddress) 

    def set(key: String, value: Object) = { 
    remoteDb ? SetRequest(key, value) 
    } 

    def get(key: String) = { 
    remoteDb ? GetRequest(key) 
    } 
} 

SClientIntegrationSpec.scala測試用例:

class SClientIntegrationSpec extends FunSpecLike with Matchers { 

    val client = new SClient("127.0.0.1:2552") 
    describe("akkadment-db-client"){ 
    it("should set a value"){ 
     client.set("jame", new Integer(1313)) 
     val futureResult = client.get("james") 
     val result = Await.result(futureResult, 10 seconds) 
     result should equal (1313) 
    } 
    } 
} 

,當我看到我的遠程應用程序的日誌,這似乎是,請求命中沒有按」 t去服務器。我的示例代碼運行時出現了什麼問題?

+1

嘿它的賈森·古德溫 - 我看到了你的鳴叫。你可以把你的代碼推到github上嗎?我已經在發佈之前檢查了所有發佈在我的github上的示例工作。我會幫你的。 – JasonG

+0

嗨@JasonG謝謝你的回覆。我沒有使用從你的倉庫下載的代碼,我正在根據你的章節創建我自己的代碼。將代碼分成兩個存儲庫服務器和客戶端。在Server Repo中,轉到第2章包https://github.com/harmeetsingh0013/Akka-practice-using-scala和客戶端repo https://github.com/harmeetsingh0013/Akka-practice-using-scala-client。正如我上面提到的,服務器代碼運行成功,但是當我試圖運行客戶端測試用例時,那麼我得到了和上面提到的異常。 –

+0

謝謝,我會在稍後檢查並回復給您。 – JasonG

回答

3

爲了解決上述問題,我們需要遵循兩個步驟是低於metnion:

  1. 當我創建一個服務器代碼,我不包括我的服務器應用程序application.conf,這就是爲什麼,客戶端應用程序不能夠與服務器連接。該代碼使用built.sbt是如下:

    mappings in (Compile, packageBin) ~= { _.filterNot { case (_, name) => 
    Seq("application.conf").contains(name) 
    }} 
    

上面的代碼註釋後,客戶端看到的服務器成功。

  • Learning Scala第2章jasongoodwin解釋客戶機和服務器系統演員的代碼。但是在書中有一些勘誤表和缺少application.conf配置的客戶端。因爲當我們在同一臺PC上運行這兩個代碼時,我們面臨已經是端口綁定異常,因爲默認情況下,參與者使用端口2552進行訪問,並且我們已經爲我們的服務器應用程序定義了此端口。所以,application.conf還需要客戶端如下:

    akka { 
        actor { 
        provider = "akka.remote.RemoteActorRefProvider" 
        } 
        remote { 
        enabled-transports = ["akka.remote.netty.tcp"] 
        netty.tcp { 
         hostname = "127.0.0.1" 
         port = 0 
        } 
        log-sent-messages = on 
        log-received-messages = on 
        } 
    } 
    
  • 這裏Port 0意味着任何空閒的端口。

    之後,上面的代碼運行成功。

    +0

    我強烈建議您按照github中提供的代碼示例進行操作,而不是自己寫。它會節省你很多時間。我對java代碼示例也是這樣做的,到目前爲止它一直是順利的。是的,你是對的,書中沒有提到客戶端代碼的application.conf。需要注意的是,客戶端和服務器都是相同的,並且需要啓用遠程配置。 – Neeraj

    +0

    非常感謝。 –

    1

    在客戶端項目中還有一個application.conf文件,這在本書中沒有提到。 確保您創建的資源文件夾下的該文件,內容如下:

    akka { 
        actor { 
        provider = "akka.remote.RemoteActorRefProvider" 
        } 
    } 
    

    official github repo

    +0

    是的,這是有效的。請注意,如果您正在運行Java示例,那麼您可能還需要配置端口「remote.netty.tcp.port = 0」,如GitHub中的Java示例所示,否則第一次運行測試時,如果將運行良好,但如果您重新運行而沒有彈起Activator,它將在隨後的嘗試中失敗。這個設置不在Scala例子中,起初對我來說有點困惑。不知道這是否是疏忽,還是Scala沒有必要。 https://github.com/jasongoodwin/learning-akka/blob/master/ch2/akkademy-db-client-java/src/main/resources/application.conf – rscarter