Akka 未来对发件人的回应

Akka Future Response to a Sender

我遇到了以下 SIP:

http://docs.scala-lang.org/sips/pending/spores.html

当我通读时,我遇到了这个例子:

def receive = {
  case Request(data) =>
    future {
      val result = transform(data)
      sender ! Response(result)
    }
}

那篇文章下面有一段描述:

>     Capturing sender in the above example is problematic, since it does not return a stable value. It is possible that the future’s body
> is executed at a time when the actor has started processing the next
> Request message which could be originating from a different actor. As
> a result, the Response message of the future might be sent to the
> wrong receiver.

我不完全理解这一行 "Capturing the sender in the above example is problematic...." 是不是在每个对 Actor (Request(data)) 的请求中都会创建一个 Future 块?

该 Future 块的创建是同步的,这意味着发送者引用在那时是已知的。只是该 Future 块的执行以某种方式安排在稍后的时间点发生。

我的理解对吗?

def receive = {
  case Request(data) =>
    future {
      val result = transform(data)
      sender ! Response(result)
    }
}

假设行 sender ! Response(result) 在 300 毫秒后执行,恰好与封闭的 actor 正在处理另一条消息的时间相同,我们称之为 M。因为 sender 是 def,而不是 val,所以每次使用时都会对其求值。这意味着,在未来,您会收到 M 消息的发件人!您没有回复创建 Future 的原始邮件的发件人,而是回复了其他人。要缓解此问题,您需要在创建 Future 时关闭 sender() def 的 值。将原始代码与此进行比较:

def receive = {
  case Request(data) =>
    val client = sender()
    future {
      val result = transform(data)
      client ! Response(result)
    }
}

您已经记住了原来的发件人,所以一切都是正确的。

最重要的是 从不 执行任何依赖于时间的方法(如 sender)或以异步方式更改 actor 的状态。如果您需要更改 actor 的状态以响应某些异步计算,您应该从 future 块向自己发送消息。