Akka 经典询问模式。它如何匹配请求与响应?

Akka Classic Ask pattern. How does it match asks with responses?

我是 Akka Actors 的新手,我正在学习 Ask 模式。我正在查看以下示例 from alvin alexander:

class TestActor extends Actor {
  def receive = {
    case AskNameMessage => // respond to the "ask" request
                           sender ! "Fred"
    case _ => println("that was unexpected")
  }
}

...

  val myActor = system.actorOf(Props[TestActor], name = "myActor")

  // (1) this is one way to "ask" another actor
  implicit val timeout = Timeout(5 seconds)
  val future = myActor ? AskNameMessage
  val result = Await.result(future, timeout.duration).asInstanceOf[String]
  println(result)

(是的,我知道 Await.result 通常不是最佳做法,但这只是一个简单的示例。)

因此,据我所知,要实现“askee”参与者来为 Ask 操作提供服务,您唯一需要做的就是通过 Tell 运算符将消息发送回“asker”,这将作为对 Ask 的回应,在“提问者”一方变成未来。看起来很简单。

我的问题是:

当响应返回时,Akka 怎么知道这个特定消息是对某个 Ask 消息的响应?

在上面的示例中,“Fred”消息不包含任何指定它是对特定 Ask 操作的响应的特定路由信息。它只是假设提问者从那个被提问者那里收到的下一条消息就是对提问的回答吗?如果是这样,那么如果一个参与者向同一个被请求者发送多个 Ask 操作怎么办?响应不会变得混乱,导致随机响应映射到错误的问题吗?

或者,如果提问者还从同一个被提问者接收到与这些提问消息无关的其他类型的消息怎么办? Asks 无法收到错误类型的响应消息吗?

澄清一下,我问的是 Akka Classic,而不是 Typed。

对于发送给参与者的每条 Ask 消息,akka 创建一个代理 ActorRef 其唯一职责是处理一条消息。这个临时“演员”是用一个承诺初始化的,它需要在消息处理时完成。

它的源代码找到了here

但主要细节是

private[akka] final class PromiseActorRef private (
    val provider: ActorRefProvider,
    val result: Promise[Any],
....

    val alreadyCompleted = !result.tryComplete(promiseResult)

现在,对于发送给接收方 askee.

的每条消息,Ask 模式都由独立的唯一参与者 asker 支持,这应该很清楚了

askee 确实知道通过方法 context.sender() 收到的每条消息的发件人或 asker 的演员参考。因此,它只需要使用此 ActorRef 将响应发送回 asker.

最后,鉴于参与者一次只处理一条消息,这一切都避免了任何竞争条件。因此,它排除了通过方法 context.sender().

检索“错误” asker 的任何可能性