web-dev-qa-db-ja.com

Akka HTTP:将来ブロックするとサーバーがブロックされます

リクエストの基本的な認証にAkka HTTPを使用しようとしています。たまたま、認証する外部リソースがあるので、このリソースに対してRESTコールを行う必要があります。

これにはしばらく時間がかかり、処理中は、APIの残りの部分がブロックされ、この呼び出しを待機しているようです。私は非常に簡単な例でこれを再現しました:

// used dispatcher:
implicit val system = ActorSystem()
implicit val executor = system.dispatcher
implicit val materializer = ActorMaterializer()


val routes = 
  (post & entity(as[String])) { e =>
    complete {
      Future{
        Thread.sleep(5000)
        e
      }
    }
  } ~
  (get & path(Segment)) { r =>
    complete {
      "get"
    }
  }

ログエンドポイントに投稿した場合、取得エンドポイントもログエンドポイントが指示する5秒間待機してスタックします。

これは予想される動作ですか、そうである場合、API全体をブロックせずにブロック操作を行うにはどうすればよいですか?

36
Kao

奇妙ですが、私にとってはすべてうまくいきます(ブロッキングなし)。ここにコードがあります:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer

import scala.concurrent.Future


object Main {

  implicit val system = ActorSystem()
  implicit val executor = system.dispatcher
  implicit val materializer = ActorMaterializer()

  val routes: Route = (post & entity(as[String])) { e =>
    complete {
      Future {
        Thread.sleep(5000)
        e
      }
    }
  } ~
    (get & path(Segment)) { r =>
      complete {
        "get"
      }
    }

  def main(args: Array[String]) {

    Http().bindAndHandle(routes, "0.0.0.0", 9000).onFailure {
      case e =>
        system.shutdown()
    }
  }
}

また、非同期コードをonCompleteまたはonSuccessディレクティブにラップすることもできます。

onComplete(Future{Thread.sleep(5000)}){e} 

onSuccess(Future{Thread.sleep(5000)}){complete(e)}
3