在调用rest api后,我想将actor的路由切换到另一条路由。 请参阅以下代码。
几个问题:
由
package com.example
import akka.actor.Actor
import akka.io.IO
import spray.httpx.RequestBuilding._
import spray.http.MediaTypes._
import spray.routing.{RoutingSettings, RejectionHandler, ExceptionHandler, HttpService}
import spray.util.LoggingContext
import scala.concurrent.Future
import spray.can.Http
import spray.http._
import akka.util.Timeout
import HttpMethods._
import akka.pattern.ask
import akka.event.Logging
import scala.concurrent.duration._
case object Swap
class MyServiceActor extends Actor with MyService with akka.actor.ActorLogging {
implicit def actorRefFactory = context
import context._
def receive = {
case Swap =>
become {
case Swap => unbecome()
case _ => runRoute(otherRoutes)
}
case _ => runRoute(myRoute)
}
}
trait MyService extends HttpService { this: MyServiceActor =>
implicit val timeout: Timeout = Timeout(15.seconds)
implicit val system = context.system
val myRoute =
{
path("") {
get {
complete("MyRoute")
}
} ~ path("swap") {
get{
self ! Swap
complete("Swapped")
}
}
}
val otherRoutes =path("") {
get {
complete("OtherRoutes")
}
} ~ path("swap") {
get{
self ! Swap
complete("Reverted")
}
}
}
答案 0 :(得分:2)
runRoute是一个部分应用的函数,所以你不能只写runRoute(routeName)
来调用它 - 它只会返回另一个函数(处理路由)但不调用它;你应该明确地传递请求对象:
def receive = {
case Swap =>
become {
case Swap => unbecome()
case x => val f = runRoute(otherRoutes); f(x)
}
case x => val f = runRoute(myRoute); f(x)
}
runRoute(route)
返回处理“已连接”消息的函数。这就是为什么你得到“注册超时”错误 - 你不从receive方法返回这个函数。当你写def receive = runRoute(route)
时,这个函数被用作处理程序,一切都很好。但是当你写def receive = {case _ => runRoute(route)}
没有任何反应时,receive
函数什么也不做,因为runRoute(route)
返回的函数无处可去。
你也可以从你的路线调用成为/不成为因为你已经将MyServiceActor作为自我类型。当您使用单独的Swap
消息时 - 在您收到成功的“交换”响应(角色更改将异步发生)后,actor可能会稍微更改其角色
case object Swap
class MyServiceActor extends Actor with MyService with akka.actor.ActorLogging {
implicit def actorRefFactory = context
import context._
def swapped = {
case x => val f = runRoute(otherRoutes); f(x)
}
def receive = {
case x => val f = runRoute(myRoute); f(x)
}
}
trait MyService extends HttpService { this: MyServiceActor =>
implicit val timeout: Timeout = Timeout(15.seconds)
implicit val system = context.system
val myRoute = {
pathSingleSlash {
get {
complete("MyRoute")
}
} ~ path("swap") {
get {
become(swapped)
complete("Swapped")
}
}
}
val otherRoutes = {
pathSingleSlash {
get {
complete("OtherRoutes")
}
} ~ path("swap") {
get{
unbecome()
complete("Reverted")
}
}
}
}
更新:您的路径匹配器也不正确。使用:
pathSingleSlash {
...
} ~ path("swap") {
...
}
或
path("swap") {
...
} ~ path("") { //matches everything else
...
}
Updated2:
确保您的演员在Main中注册为singleton:
import akka.io.IO
import spray.can.Http
implicit val system = ActorSystem()
val myListener: ActorRef = Props[MyServiceActor]
IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080)
http://spray.io/documentation/1.1-SNAPSHOT/spray-can/http-server/#http-server
答案 1 :(得分:0)
我也遇到同样的问题,那你可以把服务器参数调大一些来解决这个问题
在此处输入代码
val backlog = 50000
val standardConfig = ServerSettings("spray.can.server.ssl-encryption = off, spray.can.server.registration-timeout = 5s")
val config = standardConfig.copy(serverHeader = "REST API", sslEncryption = false, remoteAddressHeader = true)
val serviceActor = system.actorOf(Props[ApiServiceActor], "apiServiceActor")
IO(Http) ? Http.Bind(serviceActor, interface = "0.0.0.0", ConfigurationHelper.Port, settings = Some(config), backlog = backlog)