scala Akka:`ask` 模式的正确使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20124072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Akka : the proper use of `ask` pattern?
提问by head_thrash
I'm trying to grok Futuresand ask pattern in akka.
我正在尝试Futures在 akka 中了解和询问模式。
So, I make two actors, and one asking another to send him back a message. Well, according to akka's Futuresdocumentation, actor should ask(?) for message and it shall give him a Futureinstanse. Then actor should block (using Await) to get Futureresults.
所以,我制作了两个演员,一个要求另一个给他发回信息。好吧,根据 akka 的Futures文档,actor 应该向( ?)询问消息,它会给他一个Future即时的消息。然后演员应该阻止(使用Await)来获得Future结果。
Well, I never get my future done. Why is that?
好吧,我永远不会完成我的未来。这是为什么?
Code is:
代码是:
package head_thrash
import akka.actor._
import akka.util.Timeout
import scala.concurrent.Await
import scala.concurrent.duration._
object Main extends App {
val system = ActorSystem("actors")
val actor1 = system.actorOf(Props[MyActor], "node_1")
val actor2 = system.actorOf(Props[MyActor], "node_2")
actor2 ! "ping_other"
system.awaitTermination()
Console.println("Bye!")
}
class MyActor extends Actor with ActorLogging {
import akka.pattern.ask
implicit val timeout = Timeout(100.days)
def receive = {
case "ping_other" => {
val selection = context.actorSelection("../node_1")
log.info("Sending ping to node_1")
val result = Await.result(selection ? "ping", Duration.Inf) // <-- Blocks here forever!
log.info("Got result " + result)
}
case "ping" => {
log.info("Sending back pong!")
sender ! "pong"
}
}
}
If I change Duration.Infto 5.seconds, then actor waits 5 seconds, tells that my future is Timeouted(by throwing TimeoutException), and then other actor finally replies with needed message. So, no async happens. Why? :-(
如果我更改Duration.Inf为5.seconds,则 actor 等待 5 秒,告诉我的未来已超时(通过 throwing TimeoutException),然后其他 actor 最终回复所需的消息。所以,没有异步发生。为什么?:-(
How should I properly implement that pattern? Thanks.
我应该如何正确实施该模式?谢谢。
采纳答案by Arnaud Gourlay
The official Akka documentationsays that Await.result will cause the current thread to block and wait for the Actor to 'complete' the Future with it's reply.
Akka 官方文档说 Await.result 将导致当前线程阻塞并等待 Actor 用它的回复“完成”Future。
It is strange that your code blocks there forever, do you have only one thread for all your application?
奇怪的是,您的代码永远阻塞在那里,您的所有应用程序是否只有一个线程?
Anyway I guess a more "idiomatic" way to code it would be to use a callback on the future success.
无论如何,我想一种更“惯用”的编码方式是对未来的成功使用回调。
def receive = {
case "ping_other" => {
val selection = context.actorSelection("../node_1")
log.info("Sending ping to node_1")
val future: Future[String] = ask(selection, "ping").mapTo[String]
future.onSuccess {
case result : String ? log.info("Got result " + result)
}
}
...
回答by Patrik Nordwall
Two reasons why that doesn't work.
这不起作用的两个原因。
First, "node_1" asks itself and the "ping" will not be processed because it is blocking in waiting for the ask.
首先,“node_1”询问自己,“ping”不会被处理,因为它在等待询问时阻塞。
Also, there is a shortcoming of actorSelection for relative paths ("../node_1"). It is processed with message passing, and since your actor is blocking it cannot process any other message. This has been improved in upcoming 2.3 version of Akka, but you should avoid blocking anyway.
此外,相对路径(“../node_1”)的actorSelection 也有一个缺点。它通过消息传递进行处理,并且由于您的参与者正在阻止它无法处理任何其他消息。这在即将发布的 Akka 2.3 版本中得到了改进,但无论如何你应该避免阻塞。

