假设我有一些客户端代码在actor上使用akka的ask
模式:
implicit val timeout = Timeout(1.minute)
val result: Future[Any] = actor ? Question
演员就像这样处理它:
def receive = {
case Question =>
// work work work
// 3 minutes later...
sender ! Answer
}
result
期待在这种情况下会超时,因为答复将在三分钟后发送,但给定的超时只有一分钟。
akka的ask模式是否做了任何事情来通知“askee”超时?有没有办法处理这个,例如如果没有超时,取消演员可能做的剩余工作?
答案 0 :(得分:2)
这不是内置的,但如果演员准备取消,你可以完成接近这个的事情。
在发件人中,您可以执行以下操作:
...
val actorForClosure = actor
future onFailure { case _ : AskTimeoutException => actorForClosure ! Cancel }
然而,演员必须能够处理取消。如果它阻塞3分钟,那么取消请求将在计算完成并且毫无意义之后才会进入。但是,如果你可以将你的计算分解成迭代回自身的块,那么你可以在计算之间留出一个间隙让Cancel进入。因此,必须从一开始就取消。
答案 1 :(得分:2)
因此,无论提问者是否超时,您都需要一种机制来阻止长时间运行的计算。
首先,只有askee知道如何处理自己的计算。因此,它是唯一能够优雅地阻止它的人。
处理此问题的常用方法是将maximumTime
传递给消息中的askee,指示其发送完整答案的最长时间。
然后,在计算结果时,askee可以定期检查是否已达到最长时间,或者向TimeoutException
投掷Failure
或向{{1>}发送def receive = {
case MessageWithTimeout(msg, maximumTime) => compute(msg, maximumTime)
}
def compute(msg: Message, maximumTime: Long): T {
val startTime = System.nanoTime()
// ...
// somewhere during the computation:
if(System.nanoTime() - startTime > maximumTime) {
throw new TimeoutException(maximumTime + "exceeded")
}
// ...
}
:
maximumTime
这样做,askee将在{{1}}之后停止计算。
如果你发出与提问者相同的超时时间,那么提问者可能会在等待时超时,只有那时,askee才会停止计算并返回。
需要注意的是,如果你抛出一个异常,那么应该将actor的行为委托给主管。