Why are my requests handled by a single thread in spray-http?

左心房为你撑大大i 提交于 2019-12-12 11:31:34

问题


I set up an http server using spray-can, spray-http 1.3.2 and akka 2.3.6. my application.conf doesn't have any akka (or spray) entries. My actor code:

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)
}

started like this:

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

IO(Http) ! Http.Bind(restService, serviceHost, servicePort)

When I send 10 concurrent requests, they are all accepted immediately by spray and forwarded to different dispatcher actors (according to logging config for akka I have removed from applicaiton.conf lest it influenced the result), but all are handled by the same thread, which sleeps, and only after waking up picks up the next request.

What should I add/change in the configuration? From what I've seen in reference.conf the default executor is a fork-join-executor, so I'd expect all the requests to execute in parallel out of the box.


回答1:


From your code I see that there is only one TestActor to handle all requests, as you've created only one with system.actorOf. You know, actorOf doesn't create new actor per request - more than that, you have the val there, so it's only one actor. This actor handles requests sequntially one-by-one and your routes are processing inside this actor. There is no reason for dispatcher to pick-up some another thread, while the only one thread per time is used by only one actor, so you've got only one thread in the logs (but it's not guaranteed) - I assume it's first thread in the pool.

Fork-join executor does nothing here except giving first and always same free thread as there is no more actors requiring threads in parallel with current one. So, it receives only one task at time. Even with "work stealing" - it doesn't work til you have some blocked (and marked to have managed block) thread to "steal" resources from. Thread.sleep(1000) itself doesn't mark thread automatically - you should surround it with scala.concurrent.blocking to use "work stealing". Anyway, it still be only one thread while you have only one actor.

If you need to have several actors to process the requests - just pass some akka router actor (it has nothing in common with spray-router):

val restService = context.actorOf(RoundRobinPool(5).props(Props[TestActor]), "router")  

That will create a pool (not thread-pool) with 5 actors to serve your requests.



来源:https://stackoverflow.com/questions/28884268/why-are-my-requests-handled-by-a-single-thread-in-spray-http

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!