我是Akka Actors的新手,正在学习Ask模式。我正在看以下来自阿尔文·亚历山大的例子:
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操作提供服务的行动者是将消息发送回"询问";asker";通过Tell运算符;asker";作为对询问的回应。看起来很简单。
我的问题是:
当回复回来时,Akka怎么知道这个特定的消息是对某个Ask消息的回复?
在上面的例子中;弗雷德;消息不包含任何指定它是对特定Ask操作的响应的特定路由信息。它是否只是假设询问者从该询问者那里收到的下一条信息就是询问的答案?如果是这样的话,那么如果一个参与者向同一个被询问者发送多个Ask操作呢?这些响应不会变得混乱,导致随机响应被映射到错误的Ask吗?
或者,如果询问者也从同一询问者参与者那里接收到与这些询问消息无关的其他类型的消息,该怎么办?Asks不能接收错误类型的响应消息吗?
需要明确的是,我问的是阿卡经典,而不是Typed。
对于发送给参与者的每一条Ask
消息,akka都会创建一个代理ActorRef
,其唯一职责是处理一条消息。这个温度";演员;使用promise初始化,需要在消息处理时完成该promise。
它的源代码在这里找到
但主要细节是
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
。
最后,考虑到参与者一次只处理一条消息,这一切都避免了任何竞争条件。因此,它排除了检索";错误的";CCD_ 11通过方法CCD_。