如何在spray.routing中同时安全地处理路由请求?

时间:2015-11-10 01:18:47

标签: scala spray spray-routing

似乎Spray HTTP服务器的示例使用使得服务器处理请求顺序而不是并发地变得非常容易。这是正确的,因为这些示例显示了实现为一次处理一个请求的actor的路由对象(facepalm?**)。此seemsbe a共同problem

例如,下面,访问/ 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"
              )
            }
          } 
      }
    }
  }
}

**因为路由通常是无状态操作,所以制作路由器和Actor似乎没有好处,对吗?

对于我使用过的每个其他网络服务器,在接受TCP连接后几乎立即分支控制与处理程序进程或线程的连接更加明智(IMO)。 (我认为)这可以最大化接收连接的速度,并最大限度地降低无意阻塞的风险 - 至少可以完全避免路由中的无意阻塞。

更新

正如@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) }

...对于work1或work2,仍然需要大约3秒。

1 个答案:

答案 0 :(得分:2)

实际上,即使您的work2路由也有可能使HTTP Actor挨饿,因为ExecutionContext中使用的Future.applysystem.dispatcher,即喷雾HttpServiceActor的背景。我们可以为长期运行的期货提供不同的ExecutionContext,因此我们不会冒着挨饿的风险。

要回答你的问题,有一个名为setView()的指令将在某些ExecutionContext中运行剩余的路由,可能会有更多资源可用于传入请求......但因为它只是一个指令分叉在路线被击中后发生。