从演员内部的未来回到"发件人"

ani*_*u99 1 scala akka akka-cluster

我想做这样的事情 -

class MyActor extends Actor {
....
override def receive = {
  case msg =>
     .... // do something
     Future {
       ... // calculate response
       sender ! response
     }
}
}

// in some other code -
val future = myActorRef ? msg
future.onSuccess {
    ....
}
Run Code Online (Sandbox Code Playgroud)

这会有用吗?换句话说,如果响应是在"接收"方法完成之前发回的,Akka的"请求"实现是否关心?

Zol*_*tán 6

是的它会起作用,甚至还有一个内置的akka​​模式 - pipe:

import akka.pattern.pipe

override def receive = {
  case msg =>
    .... // do something
    Future {
      ... // calculate response
      response
    } pipeTo sender()
}
Run Code Online (Sandbox Code Playgroud)

但是,您的代码中应该注意一些注意事项:

sender因此,当一个Future{...}块内的代码执行时,actor可能正在处理来自另一个发件人的消息,因此您可以回复错误的发件人.为避免这种情况,请在闭包之外评估您的发件人:

val mySender = sender()
Future {
  ... // calculate response
  mySender ! response
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您使用,则无需担心pipe.


你正在将一个未来包装成一个演员并用这个演员调用ask,这再次为你提供了一个未来.如果没有演员,你应该考虑直接调用未来.如果你真的需要actor,例如因为你正在隔离一些可变状态或者消息排序很重要,你应该意识到计算Future不会发生在actor的线程上,所以你正在失去你的状态一致性和消息排序 - 另一个原因考虑失去演员,并直接呼唤未来.