Disclaimer: I have no scala experience for now, so my question is connected with very basics.
Consider the following example (it may be incomplete):
import akka.actor.{ActorSystem, Props}
import akka.io.IO
import spray.can.Http
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._
import akka.actor.Actor
import spray.routing._
import spray.http._
object Boot extends App {
implicit val system = ActorSystem("my-actor-system")
val service = system.actorOf(Props[MyActor], "my")
implicit val timeout = Timeout(5.seconds)
IO(Http) ? Http.Bind(service, interface = "localhost", port = 8080)
}
class MyActor extends Actor with MyService {
def actorRefFactory = context
def receive = runRoute(myRoute)
}
trait MyService extends HttpService {
val myRoute =
path("my") {
post {
complete {
"PONG"
}
}
}
}
My question is: what actually happens when control reaches complete
block? The question seems to be too general, so let me split it.
- I see creation of a single actor in the example. Does it mean that the application is single-threaded and uses only one cpu core?
- What happens if I do blocking call inside
complete
? - If p. 1 is true and p. 2 will block, how do I dispatch requests to utilize all cpus? I see two ways: actor per request and actor per connection. The second one seems to be reasonable, but I cannot find the way to do it using spray library.
- If the previous question is irrelevant, will
detach
directive do? And what about passing function returning Future tocomplete
directive? What is the difference between detach and passing function returning the Future? - What is the proper way to configure number of working threads and balance requests/connections?
It would be great if you point me explanations in the official documentation. It is very extensive and I believe I am missing something.
Thank you.
It's answered here by Mathias - one of the Spray authors. Copying his reply for the reference:
To answer some of your specific questions: There is only a single actor/handler that services the route thus if you make it block Spray will block. This means you want to either complete the route immediately or dispatch work using either of the 3 options above.
There are many examples on the web for these 3 options. The easiest is to wrap your code in a
Future
. Check also "actor per request" option/example. In the end your architecture will define the most appropriate way to go.Finally, Spray runs on top of Akka, so all Akka configuration still applies. See HOCON
reference.conf
andapplication.conf
for Actor threading settings.