Отправка фьючерсов в сообщениях Akka в порядке?

Я работаю над реализацией небольшого языка для отправки задач на выполнение и управления потоком выполнения. После отправки задачи в мою систему пользователь получает будущее (для которого он может вызвать блокировку get() или flatMap() ). Мой вопрос: можно ли отправлять фьючерсы в сообщениях Akka?

Пример: актор A отправляет сообщение Response актору B, а Response содержит будущее среди своих полей. Тогда в какой-то момент А выполнит обещание, из которого было создано будущее. Получив Response, B может в любой момент вызвать flatMap() или get().

Я спрашиваю, потому что сообщения Akka должны быть неизменными и работать, даже если актеры находятся на разных JVM. Я не понимаю, как мой пример выше может работать, если акторы A и B находятся на разных JVM. Кроме того, есть ли проблемы с моим примером, даже если актеры находятся на одной JVM?

Нечто подобное делается в принятом ответе в этом вопросе о стеке. . Будет ли это работать, если актеры находятся на разных JVM?


person Davor    schedule 16.12.2015    source источник


Ответы (2)


Без удаленного доступа это возможно, но все же нежелательно. С удаленным доступом в игре это вообще не сработает.

Если ваша цель состоит в том, чтобы иметь API, который возвращает Futures, но использует акторов в качестве сантехники, один из подходов может заключаться в том, что API создает внутри своего собственного актора, который он asks, а затем возвращает будущее из этого запроса вызывающей стороне. Актер, порожденный вызовом API, гарантированно является локальным для экземпляра API и может взаимодействовать с остальной частью системы акторов через обычный механизм tell/receive, так что Future не отправляется в виде сообщений.

class MyTaskAPI(actorFactory: ActorRefFactory) {

   def doSomething(...): Future[SomethingResult] = {
     val taskActor = actorFactory.actorOf(Props[MyTaskActor])
     taskActor ? DoSomething(...).mapTo[SomethingResult]
   }
 }

где MyTaskActor получает DoSomething, перехватывает отправителя, отправляет запрос на выполнение задачи и, вероятно, become является состоянием приема для SomethingResult, которое, наконец, отвечает захваченному отправителю и останавливается. Этот подход создает двух акторов для каждого запроса, один явный, MyTaskActor, и один неявно, обработчик ask, но сохраняет все состояние внутри акторов.

В качестве альтернативы вы можете использовать ActorDSL для создания только одного встроенного актера. из doSomething и использовать захваченное Promise для завершения вместо использования ask:

class MyTaskAPI(system: System) {

   def doSomething(...): Future[SomethingResult] = {
     val p = Promise[SomethingResult]()
     val tmpActor = actor(new Act {
       become {
         case msg:SomethingResult => 
            p.success(msg)
            self.stop()
       }
     }
     system.actorSelection("user/TaskHandler").tell(DoSomething(...), tmpActor)
     p.future
   }
 }

Этот подход немного не в моей голове, и он использует общее значение между API и временным актером, что некоторые могут счесть запахом, но он должен дать представление о том, как реализовать ваш рабочий процесс.

person Arne Claassen    schedule 16.12.2015
comment
Это хороший ответ на вопрос, я отметил его как ответ. Однако в моей системе могут быть одновременно миллионы задач, поэтому я хотел бы избежать создания акторов для каждой задачи из-за проблем с производительностью. Я сделаю обязательным требование, чтобы соответствующие части системы (актеры A и B в моем примере) находились на одной и той же JVM и возвращали фьючерсы. - person Davor; 17.12.2015
comment
Если ваш актор обработки просто ставит задачи в очередь, используя обещание/будущее, чтобы сигнализировать о возможной обработке и последующем завершении, все это может быть таким же простым, как использование ask напрямую. таким образом, ваш обрабатывающий актор по-прежнему получает простое сообщение и вместо того, чтобы создавать Promise и немедленно возвращать его, он сохраняет sender и выполняет tell по завершении. ask справляется с превращением этого в Future - person Arne Claassen; 17.12.2015
comment
@ArneClaassen: Почему удаленные актеры не работают в описанном им сценарии? - person stan; 17.12.2015
comment
В сценарии с запросом передача будет работать просто отлично, поскольку будущее, которое вы возвращаете, является локальной конструкцией. Приведенные выше более сложные подходы предполагали, что вы имеете в виду более сложный рабочий процесс. Я могу написать отдельный ответ только для сценария запроса, если он больше подходит для вашего вопроса. - person Arne Claassen; 17.12.2015

Если вы спрашиваете, возможно ли это, то да, возможно. Удаленные субъекты в основном представляют собой межпроцессное взаимодействие. Если вы настроите все на обеих машинах так, чтобы обе могли правильно обрабатывать будущее, то все должно быть хорошо. Вы не приводите ни одного рабочего примера, поэтому я не могу углубиться в него.

person stan    schedule 16.12.2015