Akka匹配失败和恢复

时间:2013-11-23 15:11:58

标签: scala akka actor spray

我需要帮助的东西是粗体。

我有一个飞行多个喷雾HttpRequests的actor,请求被分页并且actor确保它将结果按顺序写入数据库(序列对于恢复爬虫很重要)。我解释一下,因为我现在不想探索其他并发模式。演员需要在不重新启动的情况下从超时中恢复。

在我的演员中我有以下内容:

            case f : Failure => {
                system.log.error("faiure")
                system.log.error(s"$f")
                system.shutdown()
            }
            case f : AskTimeoutException => {
                system.log.error("faiure")
                system.log.error(s"$f")
                system.shutdown()
            }
            case msg @ _ => {

                system.log.error("Unexpected message in harvest")
                system.log.error(s"${msg}")
                system.shutdown()
            }

但我无法正确匹配:

[ERROR] [11/23/2013 14:58:10.694] [Crawler-akka.actor.default-dispatcher-3] [ActorSystem(Crawler)] Unexpected message in harvest
[ERROR] [11/23/2013 14:58:10.694] [Crawler-akka.actor.default-dispatcher-3] [ActorSystem(Crawler)] Failure(akka.pattern.AskTimeoutException: Timed out)

我的发稿如下:

abstract class CrawlerActor extends Actor {
  private implicit val timeout: Timeout = 20.seconds
  import context._
  def dispatchRequest(node: CNode) {
    val reqFut = (System.requester ? CrawlerRequest(node,Get(node.url))).map(r=> CrawlerResponse(node,r.asInstanceOf[HttpResponse]))
    reqFut pipeTo self
  }


class CrawlerRequester extends Actor  {
  import context._
  val throttler = context.actorOf(Props(classOf[TimerBasedThrottler],System.Config.request_rate),"throttler")
  throttler ! SetTarget(Some(IO(Http).actorRef))

  def receive : Receive = {
    case CrawlerRequest(type_,request) => {
      throttler forward request
    }
  }
}

一旦找到正确的匹配方式,无论如何我可以在CrawlerRequest上找到超时发生的时间吗?它包含一些我需要弄清楚如何恢复的状态。

3 个答案:

答案 0 :(得分:3)

如果您使用pipeTo来回复tell发送的邮件,则会出现这种情况。

例如:

in actorA: actorB ! message
in actorB: message => doStuff pipeTo sender
in actorA: receives not 'scala.util.Failure', but 'akka.actor.Status.Failure'

pipeTo中的其他逻辑是将Try的{​​{1}}转换为akka的演员FailureFailure)。当你使用akka.actor.Status.Failure模式时,这样可以正常工作,因为临时请求演员处理ask,但不能与akka.actor.Status.Failure一起使用。

希望这个简短的回答有帮助:)

祝你好运!

答案 1 :(得分:1)

需要输入Failure case类的完整路径,(或者我猜想导入它)。

case f: akka.actor.Status.Failure => {
                system.log.error("faiure")
                system.log.error(s"${f.cause}")
                system.shutdown()
            }

这只是留下了与超时相关的请求。在点请求调度中,似乎需要具有自定义故障处理程序的映射和管道。现在调查一下。

以下内容将超时蹦入演员。

case class CrawlerRequestTimeout(request: CrawlerRequest)
abstract class CrawlerActor extends Actor {
  private implicit val timeout: Timeout = 20.seconds
  import context._
  def dispatchRequest(node: CNode) {
    val req =  CrawlerRequest(node,Get(node.url))
    val reqFut = (System.requester ? req).map(r=> CrawlerResponse(node,r.asInstanceOf[HttpResponse]))

    reqFut onFailure {
        case te: akka.pattern.AskTimeoutException => self ! CrawlerRequestTimeout(req)
    }
    reqFut pipeTo self
  }
}

匹配:

 case timeout : CrawlerRequestTimeout => {
                println("boom")
                system.shutdown()
            }

虽然需要找到一种抑制异常的方法,但它仍在解雇。也许抑制不是真正的问题,验证。

不,抑制是一个问题,或者异常下降到msg @ _,需要放入一个案例类来吸收冗余的失败消息。

好的,所以摆脱pipeto摆脱进入客户端actor的异常。它也更容易阅读:D

abstract class CrawlerActor extends Actor {
  private implicit val timeout: Timeout = 20.seconds
  import context._
  def dispatchRequest(node: CNode) {
    val req =  CrawlerRequest(node,Get(node.url))
    val reqFut = (System.requester ? req)

    reqFut onFailure {
        case te: akka.pattern.AskTimeoutException => self ! CrawlerRequestTimeout(req)
    }
    reqFut onSuccess {
        case r: HttpResponse => self ! CrawlerResponse(node,r)
    }
  }
}

答案 2 :(得分:0)

如果我理解正确,您目前无法成功匹配AskTimeoutException

如果是这样,您应该匹配case Failure(AskTimeoutException) => ...而不是case f : AskTimeoutException => ...