1

スプレー HTTP サーバーの使用例を見ると、サーバーがリクエストを同時に処理するのではなく、順番に処理することが非常に簡単になっているようです。これは、例が一度に 1 つの要求を処理するアクターとして実装されたルーティング オブジェクトを示しているためです (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"
              )
            }
          } 
      }
    }
  }
}

** 通常、ルーティングはステートレスな操作であるため、ルーターとアクタを作成してもメリットはないようです。

私が使用した他のすべてのWebサーバーでは、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 秒かかります。

4

1 に答える 1

2

実際には、work2ルートでさえ HTTP アクターを枯渇させる可能性があります。これは、 がExecutionContext使用されているためです。つまり、スプレーのコンテキストです。長時間実行される先物には別の ExecutionContext を提供できるため、スプレーの先物を枯渇させるリスクはありません。Future.applysystem.dispatcherHttpServiceActor

ただし、質問に答えるためにdetach、一部の ExecutionContext で残りのルートを実行するというディレクティブが呼び出され、受信リクエストに対してより多くのリソースを解放する可能性があります...しかし、それはディレクティブであるため、ルートがヒットした後にのみフォークが発生します。

于 2015-11-10T16:50:17.703 に答える