如何处理请求超时?它甚至可能吗?

时间:2015-02-24 15:49:35

标签: scala akka

假设我有一些客户端代码在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”超时?有没有办法处理这个,例如如果没有超时,取消演员可能做的剩余工作?

2 个答案:

答案 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的行为委托给主管。