问题描述
目前我正在尝试实施 "actor-per-request" 模式由 NET-A-PORTER devs 在 Akka HTTP 中提出.我面临的问题是文档中的任何地方都没有记录这种模式.似乎没有办法做到以下几点:
Currently I'm trying to implement the "actor-per-request" pattern proposed by NET-A-PORTER devs in Akka HTTP. The problem I'm facing is that this pattern is not documented anywhere in the docs. There doesn't seem to be a way to do the following:
IO(Http) ! Http.Bind(serviceActor, "localhost", port = 38080)
如何在不使用 Spray 的情况下为每个请求使用一个 Akka actor?
How can I use one Akka actor per request without using Spray?
推荐答案
HttpExt
类有一个方法 bindAndHANdleAsync
可用于此目的.此方法接受具有以下签名的函数:
The HttpExt
class has a method bindAndHAndleAsync
that can be used for this purpose. This method takes in a function with the following signature:
handler: (HttpRequest) ⇒ Future[HttpResponse]
所以,假设我们有一个 Actor,当被问及 HttpRequest
时,它会产生一个 HttpResponse
:
So, suppose we have an Actor that will produce an HttpResponse
when asked about an HttpRequest
:
class HttpResponseHandlerActor extends Actor {
override def receive = {
case _ : HttpRequest =>
sender() ! HttpResponse(200, entity = "Response From Actor")
}
}
低效回答
您的问题明确询问如何为每个请求使用 1 个 Actor,为此我们现在可以使用我们的 Actor 类来创建处理函数:
Your question explicitly asks how to use 1 Actor per request, to do that we can now use our Actor class to create a handler function:
implicit val actorSystem = ActorSystem()
implicit val timeout = Timeout(5 seconds)
val handler : (HttpRequest) => Future[HttpResponse] = (httpRequest) = {
val actorHandlerRef =
system.actorOf(Props[HttpResponseHandlerActor], "responseActor")
(actorHandlerRef ask httpRequest).mapTo[HttpResponse]
}
我们现在可以使用这个函数来绑定我们的服务器:
We can now use this function to bind our server with:
val serverBinding : Future[ServerBinding] =
Http().bindAndHandleAsync(handler, "localhost", 8080)
高效回答
通常没有必要为每个请求重新创建一个新的 Actor,通常您希望创建 1 个 Actor 并为每个请求使用它.
因此,我们可以将 Actor 创建移到 handler
之外:
It is usually not necessary to re-create a new Actor for each request, typically you want to create 1 Actor and use it for every request.
Therefore we can move the Actor creation outside of handler
:
val handler : (ActorRef) => (HttpRequest) => Future[HttpResponse] =
(actorRef) => (httpRequest) =>
(actorRef ask httpRequest).mapTo[HttpResponse]
服务器绑定现在稍微修改为:
The server binding is now slightly modified to:
val singleResponseActorRef =
system.actorOf(Props[HttpResponseHandlerActor], "responseActor")
val serverBinding : Future[ServerBinding] =
Http().bindAndHandleAsync(handler(singleResponseActorRef),
"localhost",
8080)
这篇关于Akka HTTP“每个请求的参与者"图案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!