我是 Akka Actors 的新手,我正在學習 Ask 模式。我正在查看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”actor 來為 Ask 操作提供服務,您唯一需要做的就是通過 Tell 運算子將訊息發送回“asker”,這將變成未來在“詢問者”方面作為對詢問的回應。看起來很簡單。
我的問題是這樣的:
當回應回傳時,Akka 怎么知道這個特定的訊息是對某個 Ask 訊息的回應?
在上面的示例中,“Fred”訊息不包含任何指定它是對特定 Ask 操作的回應的特定路由資訊。它是否只是假設提問者從被提問者那里收到的下一條訊息是對提問的回答?如果是這樣,那么如果一個參與者向同一個被問者發送多個 Ask 操作怎么辦?回應不會很混亂,導致隨機回應映射到錯誤的 Asks 嗎?
或者,如果詢問者還從同一個被詢問者演員那里接收到與這些詢問訊息無關的其他型別的訊息怎么辦?Asks 不能收到錯誤型別的回應訊息嗎?
為了清楚起見,我問的是 Akka Classic,而不是 Typed。
uj5u.com熱心網友回復:
對于Ask發送給參與者的每條訊息,akka 都會創建一個代理ActorRef,其唯一職責是處理一條訊息。這個臨時的“演員”是用一個承諾初始化的,它需要在訊息處理中完成。
它的源代碼可以在這里找到
但主要細節是
private[akka] final class PromiseActorRef private (
val provider: ActorRefProvider,
val result: Promise[Any],
....
val alreadyCompleted = !result.tryComplete(promiseResult)
現在,應該清楚的是,asker對于發送給接收者的每條訊息,Ask 模式都由獨立的唯一參與者支持askee。
askee確實知道發送者的參與者參考,或者通過asker方法接收到的每條訊息context.sender()。因此,它只需要使用它ActorRef來將回應發送回asker.
最后,鑒于參與者一次只處理一條訊息,這一切都避免了任何競爭條件。asker因此,它排除了通過 method檢索“錯誤”的任何可能性context.sender()。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/440231.html
