【问题标题】:Is sending futures in Akka messages OK?在 Akka 消息中发送期货可以吗?
【发布时间】:2015-12-17 04:10:08
【问题描述】:

我正在努力实现一种小型语言来将任务发送到执行并控制执行流程。在向我的系统发送任务后,用户会得到一个未来(它可以在其上调用阻塞 get() 或 flatMap() )。我的问题是:可以在 Akka 消息中发送期货吗?

示例:参与者 A 向参与者 B 发送消息 Response,并且 Response 在其字段中包含未来。然后在某个时候,A 将履行创造未来的承诺。 B收到Response后,可以随时调用flatMap()或get()。

我问是因为 Akka 消息应该是不可变的并且即使参与者在不同的 JVM 上也可以工作。如果演员 A 和 B 在不同的 JVM 上,我看不出上面的示例如何工作。另外,即使演员在同一个 JVM 上,我的示例是否有任何问题?

在接受的答案in this stackoverflow question 中做了类似的事情。如果参与者在不同的 JVM 上,这会起作用吗?

【问题讨论】:

    标签: scala akka actor concurrent.futures


    【解决方案1】:

    没有远程处理是可能的,但仍然不建议这样做。在玩远程处理时,它根本不起作用。

    如果您的目标是拥有一个返回 Futures 的 API,但使用 Actor 作为底层管道,则一种方法可能是 API 在内部创建自己的 Actor,它 asks,然后返回未来从那个问来电者。 API调用产生的actor保证是API实例的本地,并且可以通过常规的tell/receive机制与actor系统的其余部分通信,因此没有Futures作为消息发送.

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

    其中MyTaskActor 接收DoSomething,捕获发送者,发送任务处理请求,并且可能becomes 为SomethingResult 的接收状态,最终响应捕获的发送者并停止自身。这种方法为每个请求创建两个参与者,一个显式地,MyTaskActor,一个隐式地,ask 的处理程序,但将所有状态保留在参与者内部。

    或者,您可以使用ActorDSL 仅创建一个内联doSomething 的actor,并使用捕获的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 和临时参与者之间的共享值,有些人可能会认为这是一种异味,但应该可以让您了解如何实现您的工作流程。

    【讨论】:

    • 这是一个很好的问题答案,我已将其标记为答案。但是,我的系统中可以同时拥有数百万个任务,因此我想避免为每个任务创建演员以解决性能问题。我将要求系统的相关部分(在我的示例中为参与者 A 和 B)在同一个 JVM 上并返回期货。
    • 如果您的处理参与者只是使用 promise/future 对任务进行排队以表示最终处理然后完成,那么整个事情可能就像直接使用 ask 一样简单。这样,您的处理参与者仍然会收到一条简单的消息,而不是创建Promise 并立即返回它,而是存储sender 并在完成时对其执行tellask 处理将其转换为 Future
    • @ArneClaassen:为什么远程演员不能在他描述的场景中工作?
    • 在询问场景中,汇款可以正常工作,因为您返回的未来是本地构造。上述更多涉及的方法假设您有一个更复杂的工作流程。如果这更适合您的问题,我可以为提问场景写一个单独的答案
    【解决方案2】:

    如果您要问是否可能,那么是的,这是可能的。远程参与者基本上是进程间通信。如果您将两台机器上的所有内容都设置为两者都可以正确处理未来的状态,那么它应该是好的。你没有给出任何有效的例子,所以我不能真正深入研究它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-17
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-28
      • 2012-11-12
      相关资源
      最近更新 更多