如果在 Spray 应用程序中超时,则杀死演员

Kill actor if it times out in Spray app

在我的 Spray 应用程序中,我将请求委托给演员。我希望能够杀死一个花费太长时间的演员。我不确定我是否应该使用 Spray 超时、Akka 请求模式或其他方式。

我已经实现了:

def processRouteRequest(system: ActorSystem) = {
  respondWithMediaType(`text/json`) {
    params { p => ctx =>
      val builder = newBuilderActor
      builder ! Request(p) // the builder calls `ctx.complete`
      builder ! PoisonPill
      system.scheduler.scheduleOnce(routeRequestMaxLife, builder, Kill)
    }
  }
}

这个想法是 actor 只在单个请求的持续时间内存在,如果它没有在 routeRequestMaxLife 内完成,它就会被强行杀死。这种方法似乎过于夸张(并且会吐出很多关于未送达消息的信息)。我什至不确定它是否正常工作。

看来我要实现的应该是一个常见的用例。我应该如何处理它?

我倾向于使用询问模式并按如下方式处理请求:

class RequestHandler extends Actor {

  def receive = {
    case "quick" => 
      sender() ! "Quick Reply"
      self ! PoisonPill

    case "slow" =>
      val replyTo = sender()
      context.system.scheduler.scheduleOnce(5 seconds, self, replyTo)

    case a:ActorRef =>
      a ! "Slow Reply"
      self ! PoisonPill
  }
}

class ExampleService extends HttpService with Actor {
  implicit def actorRefFactory = context

  import context.dispatcher

  def handleRequest(mode: String):Future[String] = {
    implicit val timeout = Timeout(1 second)
    val requestHandler = context.actorOf(Props[RequestHandler])
    (requestHandler ? mode).mapTo[String]
  }

  val route: Route =
    path("endpoint" / Segment) { str =>
      get {
        onComplete(handleRequest(str)) {
          case Success(str) => complete(str)
          case Failure(ex) => complete(ex)
        }
    }
  }

  def receive = runRoute(route)
}

这样 actor 会自行停止,Ask 的语义会为您提供有关请求是否超时的信息。