在Akka-http中完成主控制器外的请求

时间:2016-12-18 15:14:40

标签: scala migration spray akka-http

我对Akka世界很陌生,我必须将一个项目从Spray迁移到akka-http。

在喷雾中,路线的类型为Route = RequestContext ⇒ Unit 但在akka-http中,它的类型为Route = RequestContext ⇒ Future[RouteResult]

因此,在喷涂中,我们经常会通过一系列演员(主控制器之外)处理并完成我们的请求,只使用“即发即忘”,因此我们不必“询问”并且性能非常好。现在,每当我们将请求传递给另一个Actor时,我们都必须使用“ask”(如果我错了,请纠正我)

我一直在搜索很多,我找到了一些选项,我不确定他们是否完全满足我(需要在另一个Actor中完成请求而无需将其返回给控制器)​​。这就是你可以帮助我的地方:)。

选项1:使用onSuccess / onComplete
使用这个阻止我的主控制器接收更多请求吗?

选项2:使用Future并使用RouteResult.Complete

我在How to complete a request in another actor when using akka-http找到了以下示例:

import akka.actor.{ActorSystem, Actor, Props}
import akka.pattern.ask
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.{RequestContext, RouteResult}
import scala.concurrent.Future
import akka.http.scaladsl.model.HttpResponse
import akka.util.Timeout

class RequestActor extends Actor {

  //business logic - returns empty HttpResponse
  def handleRequestMessage(requestContext : RequestContext) = 
    RouteResult.Complete(new HttpResponse())

  override def receive = {
    case reqContext : RequestContext => 
      sender ! handleRequestMessage(reqContext)
  }
}//end class RequestActor

object RouteActorTest extends App {
  implicit val as = ActorSystem("RouteActorTest")
  implicit val timeout = new Timeout(1000)

  val actorRef = as actorOf Props[RequestActor]

  def handleRequest(reqContext : RequestContext) : Future[RouteResult] =
    ask(actorRef,reqContext).mapTo[RouteResult]      

  val route = path("") { get(handleRequest) }

  //rest of application...

}//end object RouteActorTest

但是这实际上每次都将响应传递给前一个Actor(发送者),直到它到达主控制器。关于这个选项的另一个问题是,在代码中,它说:

/**
 * The result of handling a request.
 *
 * As a user you typically don't create RouteResult instances directly.
 * Instead, use the methods on the [[RequestContext]] to achieve the desired effect.
 */

所以我不确定这是否是推荐的做法。

我尝试在另一个actor中使用requestContext.complete()但它不起作用(没有抛出错误,根本不发送响应) 有谁知道实现我们以前的架构的最佳方法是什么?

非常感谢!

1 个答案:

答案 0 :(得分:2)

  

需要在不需要的情况下在另一个Actor中完成请求   将其返回控制器

您不需要在另一位演员中完成请求。您需要做的就是处理请求发送回结果的actor,并且您可以使用toString()表示未来的完成:

Arrays.toString(displayWeekend)

路线:

complete

如果你想亲自手工制作case class MyRequest(data: Int) case class MyResult(data: Int) class RequestActor extends Actor { override def receive: PartialFunction[Any, Unit] = { case MyRequest(data) => sender ! MyResult(data + 1) } } ,你可以随时使用get { path("yuval") { import scala.concurrent.ExecutionContext.Implicits.global implicit val timeout = Timeout(5 seconds) complete { val result = (completionActor ? MyRequest(1)).mapTo[MyResult] result.map(r => HttpResponse(StatusCodes.OK, entity = s"Result was ${r.data}")) } } }

HttpResponse