Akka主管策略-正确的用例 [英] Akka Supervisor Strategy - Correct Use Case

查看:77
本文介绍了Akka主管策略-正确的用例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用Akka Supervisor Strategy来处理业务逻辑异常。

I have been using Akka Supervisor Strategy to handle business logic exceptions.

阅读最著名的Scala博客系列之一新植物 ,我发现他为我一直以来所做的事情提供了不同的目的。

Reading one of the most famous Scala blog series Neophyte, I found him giving a different purpose for what I have always been doing.

例如:

让我们说我有一个HttpActor,应该与外部资源联系,以防万一它掉了,我会抛出一个异常,现在是 ResourceUnavailableException

Let's say I have an HttpActor that should contact an external resource and in case it's down, I will throw an Exception, for now a ResourceUnavailableException.

万一我的Supervisor意识到了这一点,我将在HttpActor上调用Restart,在HttpActor的 preRestart 方法中,我将调用do schedulerOnce 重试一次。

In case my Supervisor catches that, I will call a Restart on my HttpActor, and in my HttpActor preRestart method, I will call do a schedulerOnce to retry that.

演员:

class HttpActor extends Actor with ActorLogging {

  implicit val system = context.system

  override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
    log.info(s"Restarting Actor due: ${reason.getCause}")
    message foreach { msg =>
      context.system.scheduler.scheduleOnce(10.seconds, self, msg)
    }
  }

  def receive = LoggingReceive {

    case g: GetRequest =>
      doRequest(http.doGet(g), g.httpManager.url, sender())
  }

一个主管:

class HttpSupervisor extends Actor with ActorLogging with RouterHelper {

  override val supervisorStrategy =
    OneForOneStrategy(maxNrOfRetries = 5) {
      case _: ResourceUnavailableException   => Restart
      case _: Exception                      => Escalate
    }

  var router = makeRouter[HttpActor](5)

  def receive = LoggingReceive {
    case g: GetRequest =>
      router.route(g, sender())

    case Terminated(a) =>
      router = router.removeRoutee(a)
      val r = context.actorOf(Props[HttpActor])
      context watch r
      router = router.addRoutee(r)
  }
}

这是什么意思?

如果我的 doRequest 方法抛出 ResourceUnavailableException ,主管将获取该信息并重新启动actor ,根据调度程序,迫使它在一段时间后重新发送消息。我看到的优点是我免费获得了重试次数以及处理异常本身的好方法。

In case my doRequest method throws the ResourceUnavailableException, the supervisor will get that and restart the actor, forcing it to resend the message after some time, according to the scheduler. The advantages I see is the fact I get for free the number of retries and a nice way to handle the exception itself.

现在看博客,他发现了一个不同的例子。万一您需要重试的方法,只需发送这样的消息即可:

Now looking at the blog, he shows a different approach in case you need a retry stuff, just sending messages like this:

def receive = {
  case EspressoRequest =>
    val receipt = register ? Transaction(Espresso)
    receipt.map((EspressoCup(Filled), _)).recover {
      case _: AskTimeoutException => ComebackLater
    } pipeTo(sender)

  case ClosingTime => context.system.shutdown()
}

如果 Future 的> AskTimeoutException ,他通过管道将结果作为 ComebackLater 对象,

Here in case of AskTimeoutException of the Future, he pipes the result as a ComebackLater object, which he will handle doing this:

case ComebackLater =>
      log.info("grumble, grumble")
      context.system.scheduler.scheduleOnce(300.millis) {
        coffeeSource ! EspressoRequest
      }

对我来说,您可以使用策略主管来做很多事情,

For me this is pretty much what you can do with the strategy supervisor, but in a manually way, with no built in number of retries logic.

那么这里最好的方法是什么?为什么呢?我使用akka主管策略的概念是完全错误的吗?

So what is the best approach here and why? Is my concept of using akka supervisor strategy completely wrong?

推荐答案

您可以使用 BackoffSupervisor


以内置模式提供 akka.pattern.BackoffSupervisor 实施所谓的指数退避监管策略,在子角色失败时重新启动子角色,每次重新启动之间的时间间隔都会越来越长。

Provided as a built-in pattern the akka.pattern.BackoffSupervisor implements the so-called exponential backoff supervision strategy, starting a child actor again when it fails, each time with a growing time delay between restarts.



val supervisor = BackoffSupervisor.props(
  Backoff.onFailure(
    childProps,
    childName = "myEcho",
    minBackoff = 3.seconds,
    maxBackoff = 30.seconds,
    randomFactor = 0.2 // adds 20% "noise" to vary the intervals slightly 
  ).withAutoReset(10.seconds) // the child must send BackoffSupervisor.Reset to its parent 
  .withSupervisorStrategy(
    OneForOneStrategy() {
      case _: MyException => SupervisorStrategy.Restart
      case _ => SupervisorStrategy.Escalate
    }))

这篇关于Akka主管策略-正确的用例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆