【问题标题】:How can I safely process routing requests concurrently in spray.routing?如何在 spray.routing 中安全地同时处理路由请求?
【发布时间】:2015-11-10 01:18:47
【问题描述】:

Spray HTTP 服务器的示例使用似乎使服务器按顺序而不是同时处理请求变得非常容易。这是正确的,因为示例显示路由对象实现为一次处理一个请求的参与者(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 秒。

【问题讨论】:

    标签: scala spray spray-routing


    【解决方案1】:

    实际上,即使您的 work2 路由也有可能使 HTTP Actor 饿死,因为 Future.apply 中使用的 ExecutionContextsystem.dispatcher,即喷雾 HttpServiceActor 的上下文。我们可以为长期运行的期货提供不同的 ExecutionContext,这样我们就不会冒着饿死喷雾的风险。

    不过,要回答您的问题,有一个名为 detach 的指令将在某些 ExecutionContext 中运行路由的其余部分,可能会为传入的请求留出更多资源......但因为它是一个指令,只在之后发生分叉路线被击中。

    【讨论】:

    • 这似乎有帮助,但如果我执行 10 个请求,总共需要 >3 秒(调用 work1 或 work2 时)。用我的工作更新了这个问题。
    猜你喜欢
    • 1970-01-01
    • 2016-05-05
    • 1970-01-01
    • 2014-04-02
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 2014-11-29
    • 2015-09-13
    相关资源
    最近更新 更多