加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何使用ask模式和监督来处理异常

发布时间:2020-12-16 08:56:48 所属栏目:安全 来源:网络整理
导读:我应该如何处理DbActor抛出的异常?我不确定如何处理它,应该管道故障情况? class RestActor extends Actor with ActorLogging { import context.dispatcher val dbActor = context.actorOf(Props[DbActor]) implicit val timeout = Timeout(10 seconds) ove
我应该如何处理DbActor抛出的异常?我不确定如何处理它,应该管道故障情况?

class RestActor extends Actor with ActorLogging {
  import context.dispatcher

  val dbActor = context.actorOf(Props[DbActor])
  implicit val timeout = Timeout(10 seconds)


  override val supervisorStrategy: SupervisorStrategy = {
    OneForOneStrategy(maxNrOfRetries = 10,withinTimeRange = 10 seconds) {
      case x: Exception => ???
    }
  }

  def receive = {
    case GetRequest(reqCtx,id) => {

        // perform db ask
       ask(dbActor,ReadCommand(reqCtx,id)).mapTo[SomeObject] onComplete {
        case Success(obj) => { // some stuff }
        case Failure(err) => err match {
          case x: Exception => ???
        }
      }
    }
  }
}

很高兴得到你的想法,提前谢谢!

解决方法

根据代码示例中的问题,我可以在此处看到几个问题:

  1. What types of things can I do when I override the default supervisor behavior in the definition of how to handle exceptions?

  2. When using ask,what types of things can I do when I get a Failure result on the Future that I am waiting on?

让我们先从第一个问题开始(通常是一个好主意).当您覆盖默认管理程序策略时,您可以更改如何处理子actor中某些类型的未处理异常,以了解如何处理该失败的子actor.前一句中的关键词未处理.对于正在执行请求/响应的actor,您实际上可能希望处理(捕获)特定异常并返回某些响应类型(或者上游未来失败,稍后更多),而不是让它们处理不当.当发生未处理的异常时,您基本上失去了使用问题描述来响应发送方的能力,然后发送方可能会获得TimeoutException,因为它们的Future永远不会完成.一旦明确了解了处理的内容,就可以在定义自定义管理程序策略时考虑所有其余的异常.这个街区在这里:

OneForOneStrategy(maxNrOfRetries = 10,withinTimeRange = 10 seconds) {
  case x: Exception => ???
}

您有机会将异常类型映射到故障指令,该指令定义了如何从监管角度处理故障.选项是:

>停止 – 完全停止子actor并且不再向其发送任何消息
>恢复 – 恢复失败的孩子,而不是重新启动它,从而保持其当前的内部状态
>重新启动 – 与resume类似,但在这种情况下,抛弃旧实例并构造新实例并重置内部状态(preStart)
>升级 – 将链升级到主管的父级

所以,假设你想要恢复并给出你要重启的所有其他人的SQLException,那么你的代码将如下所示:

OneForOneStrategy(maxNrOfRetries = 10,withinTimeRange = 10 seconds) {
  case x: SQLException => Resume
  case other => Restart
}

现在讨论第二个问题,它涉及当Future本身返回Failure响应时该怎么做.在这种情况下,我猜这取决于未来应该发生的事情.如果其余的actor本身负责完成http请求(让我们说httpCtx上有一个完整的(statusCode:Int,message:String)函数),那么你可以这样做:

ask(dbActor,id)).mapTo[SomeObject] onComplete {
    case Success(obj) => reqCtx.complete(200,"All good!")
    case Failure(err:TimeoutException) => reqCtx.complete(500,"Request timed out")
    case Failure(ex) => reqCtx.complete(500,ex.getMessage)
  }

现在,如果上游的另一个actor负责完成http请求并且您需要响应该actor,您可以执行以下操作:

val origin = sender
   ask(dbActor,id)).mapTo[SomeObject] onComplete {
    case Success(obj) => origin ! someResponSEObject
    case Failure(ex) => origin ! Status.Failure(ex)
  }

这种方法假设在成功块中,您首先要在响应之前按摩结果对象.如果您不想这样做并且想要将结果处理推迟给发件人,那么您可以这样做:

val origin = sender
   val fut = ask(dbActor,id))
   fut pipeTo origin

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读