我对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()但它不起作用(没有抛出错误,根本不发送响应) 有谁知道实现我们以前的架构的最佳方法是什么?
非常感谢!
答案 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