Кажется, что примеры использования HTTP-сервера Spray упрощают процесс обработки сервером запросов последовательно, а не одновременно. Это верно, потому что в примерах показан объект маршрутизации, реализованный как актор, обрабатывающий один запрос за раз (facepalm?**). Это кажется быть общим проблема.
Например, ниже при доступе к /work1 запрос обрабатывается асинхронно, но для /work2 мы, к сожалению, блокируем ВСЕ другие запросы (предположим, например, что /work2 должен быть занят аутентификацией маркера из файла cookie в базе данных).
Есть ли способ использовать spray.routing, где выполнение разветвляется до перехода к маршрутизации?
import akka.actor.ActorSystem
import spray.http.{MediaTypes, HttpEntity}
import spray.routing.SimpleRoutingApp
import scala.concurrent.Future
class MySimpleServer(val system: ActorSystem, val HOST: String, val PORT: Int) extends SimpleRoutingApp {
implicit val _system: ActorSystem = system
import _system.dispatcher
def main(args: Array[String]): Unit = {
startServer(interface = HOST, port = PORT) {
get {
path("work1") {
complete {
// Asynchronously process some work
Future.apply {
Thread.sleep(1000)
HttpEntity(
MediaTypes.`text/html`,
"OK"
)
}
}
} ~
path("work2") {
complete {
// Synchronously process some work and block all routing for this Actor.
// Oh sh*t!
Thread.sleep(1000)
HttpEntity(
MediaTypes.`text/html`,
"OK"
)
}
}
}
}
}
}
** поскольку маршрутизация, как правило, является операцией без сохранения состояния, кажется, что нет смысла создавать маршрутизатор и актера, верно?
Для каждого другого веб-сервера, который я использовал, разветвление управления соединением с процессом-обработчиком или потоком более разумно (IMO) происходит почти сразу после принятия TCP-соединения. (Я думаю) это максимизирует скорость, с которой могут быть получены соединения, и минимизирует риск непреднамеренной блокировки - по крайней мере, полностью предотвращает непреднамеренную блокировку при маршрутизации.
Обновлять:
Как предложил @rahilb
detach() {
get {...} ..
}
и вызов как:
val responses = (0 until 10)
.map { _ => (IO(Http) ? HttpRequest(GET, s"${TEST_BASE_URL}work1")).mapTo[HttpResponse] }
.map { response => Await.result(response, 5 seconds) }
... по-прежнему занимает около> 3 секунд для work1 или work2.