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

时间:2016-07-25 15:21:04

标签: 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 {
    ....
}

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

2 个答案:

答案 0 :(得分:6)

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

import akka.pattern.pipe

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

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

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

val mySender = sender()
Future {
  ... // calculate response
  mySender ! response
}

如果您使用pipe,则无需担心此问题。

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

答案 1 :(得分:1)

问题是,当执行未来时,{{ joomlaComponent }}可能不再有效。你有两个选择,这里有两个选项:

您可以在未来之前捕获 sender

sender

或者您可以使用 pipeTo 模式:

override def receive = {
  case msg =>
     .... // do something
     val replyTo = sender

     Future {
       ... // calculate response
       replyTo ! response
     }
}