Scala askee应该如何处理ask超时?有可能吗?

Scala askee应该如何处理ask超时?有可能吗?,scala,akka,Scala,Akka,假设我有一些客户端代码,在一个演员身上使用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 } 在这种情况下,结果未来将超

假设我有一些客户端代码,在一个演员身上使用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
}
在这种情况下,
结果
未来将超时,因为回复将在三分钟后发送,但给定的超时时间仅为一分钟


akka的ask模式是否会通知“askee”超时?是否有办法处理此问题,例如取消参与者在没有超时的情况下可能完成的任何剩余工作?

这不是内置的,但如果参与者准备取消,您可以完成类似的工作

在发件人中,您可以执行以下操作:

...
val actorForClosure = actor
future onFailure { case _ : AskTimeoutException => actorForClosure ! Cancel }

然而,演员必须能够处理取消。如果它阻塞了3分钟,那么cancel请求将在计算完成后才会进入,并且没有意义。但是,如果您可以将计算分解为块,然后迭代回自身,那么您就可以在计算之间留出一个间隙,让Cancel进入。因此,取消必须从一开始就准备好。

这不是内置的,但是如果演员准备取消,你可以完成类似的事情

在发件人中,您可以执行以下操作:

...
val actorForClosure = actor
future onFailure { case _ : AskTimeoutException => actorForClosure ! Cancel }
然而,演员必须能够处理取消。如果它阻塞了3分钟,那么cancel请求将在计算完成后才会进入,并且没有意义。但是,如果您可以将计算分解为块,然后迭代回自身,那么您就可以在计算之间留出一个间隙,让Cancel进入。因此,取消必须从一开始就进行。

问题 因此,无论询问者是否超时,您都需要一个机制来停止askee中发生的长时间运行的计算

解决办法 首先,只有askee知道如何处理自己的计算。因此,它是唯一能够优雅地阻止它的人

处理此问题的一种常见方法是在消息中向askee传递
maximumTime
,指示其发送完整答案的最长时间

然后,在计算其结果时,askee可以定期检查是否已达到最大时间,或者抛出
TimeoutException
,或者向询问者发送
故障

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")
  }
  // ...
}
这样,askee将在
最大时间后停止计算

如果您发送的超时与asker的超时相同,那么asker很可能会在等待时超时,只有到那时askee才会停止计算并返回

需要注意的是,如果抛出异常,那么参与者的行为应该委托给主管。

问题 因此,无论询问者是否超时,您都需要一个机制来停止askee中发生的长时间运行的计算

解决办法 首先,只有askee知道如何处理自己的计算。因此,它是唯一能够优雅地阻止它的人

处理此问题的一种常见方法是在消息中向askee传递
maximumTime
,指示其发送完整答案的最长时间

然后,在计算其结果时,askee可以定期检查是否已达到最大时间,或者抛出
TimeoutException
,或者向询问者发送
故障

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")
  }
  // ...
}
这样,askee将在
最大时间后停止计算

如果您发送的超时与asker的超时相同,那么asker很可能会在等待时超时,只有到那时askee才会停止计算并返回


需要注意的是,如果抛出异常,则应将参与者的行为委托给主管。

简短的回答是否。参与者不能被打断处理其正在处理的当前消息。与参与者的任何通信都是通过消息进行的(甚至是停止之类的事情),在当前消息完成之前,不会处理新消息。现在,如果您的参与者将部分工作分包出去,然后切换状态以等待响应,那么它可以处理另一条消息,告诉它在第一个响应返回后停止并不要完成任何其他工作,但您需要自己编写代码。Ask本身不处理此问题。简短的回答是“否”。参与者不能被打断处理其正在处理的当前消息。与参与者的任何通信都是通过消息进行的(甚至是停止之类的事情),在当前消息完成之前,不会处理新消息。现在,如果您的参与者将部分工作分包出去,然后切换状态以等待响应,那么它可以处理另一条消息,告诉它在第一个响应返回后停止并不要完成任何其他工作,但您需要自己编写代码。Ask本身不处理这个问题。