Akka 为什么我的请求在spray http中由一个线程处理?

Akka 为什么我的请求在spray http中由一个线程处理?,akka,spray,Akka,Spray,我使用spray can、spray http 1.3.2和akka 2.3.6设置了一个http服务器。 我的application.conf没有任何akka(或spray)条目。我的演员代码: class TestActor extends HttpServiceActor with ActorLogging with PlayJsonSupport { val route = get { path("clientapi"/"orders") { complet

我使用spray can、spray http 1.3.2和akka 2.3.6设置了一个http服务器。 我的application.conf没有任何akka(或spray)条目。我的演员代码:

class TestActor extends HttpServiceActor with ActorLogging with PlayJsonSupport {
  val route = get { 
    path("clientapi"/"orders") { 
       complete {{
            log.info("handling request")
            System.err.println("sleeping "+Thread.currentThread().getName)
            Thread.sleep(1000)
            System.err.println("woke up "+Thread.currentThread().getName)
            Seq[Int]()
       }}
    }
  }

  override def receive: Receive = runRoute(route)
}
开始是这样的:

val restService = system.actorOf(Props(classOf[TestActor]), "rest-clientapi")

IO(Http) ! Http.Bind(restService, serviceHost, servicePort)
当我发送10个并发请求时,spray会立即接受它们,并将它们转发给不同的dispatcher参与者(根据akka的日志配置,我已从applicationon.conf中删除,以免影响结果),但所有请求都由同一个线程处理,该线程处于休眠状态,只有在唤醒后才会接收下一个请求


我应该在配置中添加/更改什么?从我在reference.conf中看到的默认执行器是一个fork-join执行器,因此我希望所有请求都能在开箱即用的情况下并行执行。

从您的代码中,我看到只有一个
TestActor
来处理所有请求,因为您只使用
system.actorOf
创建了一个。你知道,
actorOf
不会为每个请求创建新的参与者-更重要的是,这里有
val
,所以只有一个参与者。此actor逐个处理请求,并且您的路由正在该actor内处理。dispatcher没有理由选择另一个线程,而每次只有一个线程由一个参与者使用,因此日志中只有一个线程(但不能保证)——我假设它是池中的第一个线程

Fork-join-executor在这里什么也不做,只提供第一个始终相同的空闲线程,因为并没有更多的参与者需要线程与当前线程并行。因此,它一次只接收一个任务。即使使用了“工作窃取”,它也不起作用,除非您有一些阻塞(并标记为具有托管块)线程来“窃取”资源<代码>线程.sleep(1000)本身不会自动标记线程-您应该用“工作窃取”来包围它。无论如何,当你只有一个演员时,它仍然只有一个线程

如果您需要几个参与者来处理请求,只需传递一些(它与spray router没有任何共同之处):


这将创建一个包含5个参与者的池(不是线程池)来处理您的请求。

从您的代码中,我看到只有一个参与者(TestActor)来处理所有请求,因为您只使用
system.actorOf
创建了一个参与者。dispatcher没有理由选择一些新的线程,而每次只有一个线程被一个参与者使用。我想我知道我的困惑是从哪里来的。我确信Route是一个curried函数rq=>rq=>(),我的服务只负责路由返回处理程序函数,该函数将由spray管理的参与者池执行。相反,我必须自己配置池,并在Bind消息中将ActorRef发送到路由器。我不明白为什么在任何示例中都没有提到这一点,我没想到会使用参考配置和喷洒路线进行生产调整,但单线程模型让我感到意外。您和其他很多人都是如此。这些例子使人们走上了死胡同,并没有充分解释不在路由器中释放新工作人员的陷阱(特别是因为大多数HTTP服务器架构在此之前已经分叉)。
val restService = context.actorOf(RoundRobinPool(5).props(Props[TestActor]), "router")