喜欢 + 在时间范围内

Akka + WithinTimeRange

我已经测试了 akka 的容错系统,到目前为止,在谈论根据指定的 maxNrOfRetries 重试发送消息时,它一直很好。

但是,它不会在给定的时间范围内重新启动 actor,它会立即重新启动,忽略时间范围内的内容。

我尝试使用 AllForOneStrategy 和 OneForOneStrategy 但没有改变任何东西。

正在尝试关注此博客 post:http://letitcrash.com/post/23532935686/watch-the-routees,这是我一直在使用的代码。

class Supervisor extends Actor with ActorLogging {

  var replyTo: ActorRef = _

  val child = context.actorOf(
    Props(new Child)
      .withRouter(
        RoundRobinPool(
          nrOfInstances = 5,
          supervisorStrategy =
            AllForOneStrategy(maxNrOfRetries = 3, withinTimeRange = 10.second) {
              case _: NullPointerException     => Restart
              case _: Exception                => Escalate
            })), name = "child-router")

  child ! GetRoutees

  def receive = {
    case RouterRoutees(routees) =>
      routees foreach context.watch

    case "start" =>
      replyTo = sender()
      child ! "error"

    case Terminated(actor) =>
      replyTo ! -1
      context.stop(self)
  }
}

class Child extends Actor with ActorLogging {

  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    log.info("***** RESTARTING *****")
    message foreach{ self forward }
  }

  def receive = LoggingReceive {
    case "error" =>
      log.info("***** GOT ERROR *****")
      throw new NullPointerException
  }
}

object Boot extends App {

  val system = ActorSystem()
  val supervisor = system.actorOf(Props[Supervisor], "supervisor")

  supervisor ! "start"

}

我这样做有什么不对吗?

编辑

其实我误解了withinTimeRange的用途。 要在某个时间范围内安排我的重试,我正在执行以下操作:

override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    log.info("***** RESTARTING *****")
    message foreach { msg =>
      context.system.scheduler.scheduleOnce(30.seconds, self, msg)
    }
  }

好像还可以。

我认为您误解了 withinTimeRange 参数的用途。该值应该与 maxNrOfRetries 结合使用以提供 window 以支持限制重试次数。例如,正如您所指定的,这意味着如果 child 需要在 10 秒内重新启动超过 3 次,主管将不再重新启动个人 child。

来自文档:

maxNrOfRetries - the number of times a child actor is allowed to be restarted, negative value means no limit, if the limit is exceeded the child actor is stopped

withinTimeRange - duration of the time window for maxNrOfRetries, Duration.Inf means no window

您的代码意味着当任何 child 在 10 秒内以 NullPointerException 失败超过 3 次时,它将不会再次重新启动。由于 AllForOneStrategy 在第一个路由失败后所有路由都重新启动。并且因为您已经覆盖 preRestart 以重新发送失败的消息,这种情况会再次重复,直到在 10 秒内达到 3 次失败(在不到一秒内实现)。