从演员内部的未来回到 "sender"
Returning to "sender" from a future inside an actor
我想做这样的事情-
class MyActor extends Actor {
....
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
sender ! response
}
}
}
// in some other code -
val future = myActorRef ? msg
future.onSuccess {
....
}
这行得通吗?换句话说,Akka 的 "ask" 实现是否关心响应是否在 "receive" 方法完成之前发回?
是的,它会起作用,甚至还有一个内置的 akka 模式 - pipe
:
import akka.pattern.pipe
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
response
} pipeTo sender()
}
但是您应该注意代码中的一些注意事项:
sender
是一个函数,因此,当您的 Future{...}
块中的代码执行时,参与者可能正在处理来自另一个发件人的消息,因此您可能会回复错误的发件人。为避免这种情况,请在闭包之外评估您的发件人:
val mySender = sender()
Future {
... // calculate response
mySender ! response
}
不过,如果您使用 pipe
,则无需担心这一点。
你正在将一个未来包装到一个演员中,并用 ask
调用那个演员,这又给了你一个未来。你真的应该考虑直接调用未来,而不是演员。
如果你真的需要演员,例如因为你正在隔离一些可变状态或消息排序很重要,你应该知道计算 Future
不会发生在演员的线程上,所以你正在失去你的状态一致性和消息排序 - 考虑失去的另一个原因演员,并直接调用未来。
问题是,当执行 future 时,sender
可能不再有效。你有几个选择,这里有两个是我想到的:
您可以捕获未来sender
之前的
override def receive = {
case msg =>
.... // do something
val replyTo = sender
Future {
... // calculate response
replyTo ! response
}
}
或者您可以使用 pipeTo 模式:
override def receive = {
case msg =>
.... // do something
import akka.pattern.pipe
Future {
... // calculate response
}.pipeTo(sender())
}
我想做这样的事情-
class MyActor extends Actor {
....
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
sender ! response
}
}
}
// in some other code -
val future = myActorRef ? msg
future.onSuccess {
....
}
这行得通吗?换句话说,Akka 的 "ask" 实现是否关心响应是否在 "receive" 方法完成之前发回?
是的,它会起作用,甚至还有一个内置的 akka 模式 - pipe
:
import akka.pattern.pipe
override def receive = {
case msg =>
.... // do something
Future {
... // calculate response
response
} pipeTo sender()
}
但是您应该注意代码中的一些注意事项:
sender
是一个函数,因此,当您的 Future{...}
块中的代码执行时,参与者可能正在处理来自另一个发件人的消息,因此您可能会回复错误的发件人。为避免这种情况,请在闭包之外评估您的发件人:
val mySender = sender()
Future {
... // calculate response
mySender ! response
}
不过,如果您使用 pipe
,则无需担心这一点。
你正在将一个未来包装到一个演员中,并用 ask
调用那个演员,这又给了你一个未来。你真的应该考虑直接调用未来,而不是演员。
如果你真的需要演员,例如因为你正在隔离一些可变状态或消息排序很重要,你应该知道计算 Future
不会发生在演员的线程上,所以你正在失去你的状态一致性和消息排序 - 考虑失去的另一个原因演员,并直接调用未来。
问题是,当执行 future 时,sender
可能不再有效。你有几个选择,这里有两个是我想到的:
您可以捕获未来sender
之前的
override def receive = {
case msg =>
.... // do something
val replyTo = sender
Future {
... // calculate response
replyTo ! response
}
}
或者您可以使用 pipeTo 模式:
override def receive = {
case msg =>
.... // do something
import akka.pattern.pipe
Future {
... // calculate response
}.pipeTo(sender())
}