被请求者应该如何处理请求超时?有可能吗?
How should an ask timeout be handled by the askee? Is it even possible?
假设我有一些客户端代码在 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
Future 预计会超时,因为回复将在三分钟后发送,但给定的超时仅为一分钟。
akka 的询问模式是否会采取任何措施来通知 "askee" 超时?有没有办法处理这个,例如取消演员在没有超时的情况下可能完成的任何剩余工作?
这不是内置的,但如果演员准备取消,您可以完成类似的事情。
在您的发件人中,您可以执行以下操作:
...
val actorForClosure = actor
future onFailure { case _ : AskTimeoutException => actorForClosure ! Cancel }
但是,演员必须能够处理取消。如果它阻塞了 3 分钟,那么取消请求直到计算完成后才会进入并且毫无意义。但是,如果您可以将计算分解为迭代回其自身的块,那么您可以在计算之间为 Cancel 留出间隙。因此,必须从一开始就考虑取消。
问题
所以你需要一种机制来停止在被询问者中进行的长时间 运行 计算,无论询问者是否超时。
一个解决方案
首先,只有被询问者才知道如何处理自己的计算。所以,只有它能优雅的阻止它。
处理此问题的常用方法是在消息中将 maximumTime
传递给被询问者,指示其发送完整答案的最长时间。
然后,在计算结果时,被请求者可以定期检查是否达到了最大时间,或者抛出一个 TimeoutException
或发送一个 Failure
给请求者:
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
后停止计算。
如果你发送与asker相同的超时,那么很可能asker会在等待时超时,然后askee才会停止计算并且return.
需要注意的是,如果你抛出异常,那么演员的行为应该委托给监管者。
假设我有一些客户端代码在 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
Future 预计会超时,因为回复将在三分钟后发送,但给定的超时仅为一分钟。
akka 的询问模式是否会采取任何措施来通知 "askee" 超时?有没有办法处理这个,例如取消演员在没有超时的情况下可能完成的任何剩余工作?
这不是内置的,但如果演员准备取消,您可以完成类似的事情。
在您的发件人中,您可以执行以下操作:
...
val actorForClosure = actor
future onFailure { case _ : AskTimeoutException => actorForClosure ! Cancel }
但是,演员必须能够处理取消。如果它阻塞了 3 分钟,那么取消请求直到计算完成后才会进入并且毫无意义。但是,如果您可以将计算分解为迭代回其自身的块,那么您可以在计算之间为 Cancel 留出间隙。因此,必须从一开始就考虑取消。
问题
所以你需要一种机制来停止在被询问者中进行的长时间 运行 计算,无论询问者是否超时。
一个解决方案
首先,只有被询问者才知道如何处理自己的计算。所以,只有它能优雅的阻止它。
处理此问题的常用方法是在消息中将 maximumTime
传递给被询问者,指示其发送完整答案的最长时间。
然后,在计算结果时,被请求者可以定期检查是否达到了最大时间,或者抛出一个 TimeoutException
或发送一个 Failure
给请求者:
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
后停止计算。
如果你发送与asker相同的超时,那么很可能asker会在等待时超时,然后askee才会停止计算并且return.
需要注意的是,如果你抛出异常,那么演员的行为应该委托给监管者。