Akka Actor: исключение удаленного актера Время ожидания истекло после

Я новичок в Akka, я использую версию Akka 2.3.3 для создания актеров. Я собираюсь создать удаленного актера и попытаться получить доступ с помощью клиента. Всякий раз, когда я собираюсь запустить тестовый пример, будет выдано следующее исключение:

[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())
  }
 }

Код клиента, как показано ниже: 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://SimpleClientServer@$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)
    }
  }
}

Когда я вижу журналы своего удаленного приложения, похоже, что полученный запрос не попадает на сервер. в чем проблема в моем примере кода?


person Harmeet Singh Taara    schedule 27.04.2016    source источник
comment
эй, это Джейсон Гудвин - я видел твой твит. Можете ли вы разместить свой код на гитхабе? Я проверил все примеры работы перед публикацией, которые размещены на моем github. Я протяну тебе руку помощи.   -  person JasonG    schedule 27.04.2016
comment
привет @JasonG, спасибо за ответ. Я не использую загруженный код из вашего репозитория, я создаю свой собственный согласно вашим главам. Разделите код на два репозитория: сервер и клиент. В Server Repo перейдите к пакету главы 2 github.com/harmeetsingh0013/Akka-practice-using- scala и клиентское репозиторий github.com/harmeetsingh0013/Akka-practice- using-scala-client. Как я уже упоминал выше, код сервера работает успешно, но когда я пытаюсь запустить тестовый пример клиента, я получил исключение, как упомянуто выше.   -  person Harmeet Singh Taara    schedule 28.04.2016
comment
спасибо, посмотрю позже и свяжусь с вами.   -  person JasonG    schedule 28.04.2016
comment
Танки @JasonG, буду ждать вашего ответа.   -  person Harmeet Singh Taara    schedule 29.04.2016


Ответы (2)


Для решения вышеуказанной проблемы нам нужно выполнить два шага, описанные ниже:

  1. Когда я создаю серверный код, я исключаю application.conf из своего серверного приложения, поэтому клиентское приложение не может подключиться к серверу. Код, используемый в built.sbt, выглядит следующим образом:

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

Комментируя приведенный выше код, клиент успешно видит сервер.

  1. В Learning Scala главе 2 jasongoodwin объясняется код системы акторов клиента и сервера. Но в книге есть некоторые исправления и отсутствует application.conf конфигурация для клиента. Потому что, когда мы запускаем оба кода на одном ПК, мы уже сталкиваемся с исключением привязки порта, потому что по умолчанию акторы используют порт 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 означает любой свободный порт.

После этого приведенный выше код работает успешно.

person Harmeet Singh Taara    schedule 30.04.2016
comment
Я настоятельно рекомендую вам следовать образцу кода, приведенному в github, а не писать самостоятельно. Это сэкономит ваше время. Я делаю то же самое с образцами кода Java, и до сих пор это был гладкий путь. Да, вы правы, application.conf для клиентского кода в книге не упоминался. Следует отметить, что клиент и сервер одинаковы и требуют включения удаленной конфигурации. - person Neeraj Singh; 30.07.2016
comment
Большое спасибо. - person Jintao Guan; 08.08.2017

В клиентском проекте также есть файл application.conf, который не упоминается в книге. Убедитесь, что вы создали этот файл в папке ресурсов со следующим содержимым:

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

См. официальное репозиторий github

person khlumzeemee    schedule 18.07.2017
comment
Да, это работает. Просто обратите внимание, что если вы запускаете пример Java, вам также может потребоваться настроить порт remote.netty.tcp.port = 0, как показано в примере Java в GitHub, в противном случае при первом запуске теста, все будет нормально , но если вы снова запустите его без подпрыгивания активатора, он не удастся при последующих попытках. Этого параметра нет в примере Scala, что поначалу меня немного сбивало с толку. Не уверен, что это недосмотр или это просто не нужно для Scala. github.com/jasongoodwin/learning-akka/blob/master/ch2/ - person rscarter; 01.10.2017