0

私はプレイを持っています!httpリクエストを送信して別のサーバーと通信するScalaアプリケーション。このシステムには制限があります。1 つのトークンに対して同時に処理できる HTTP リクエストは 5 つだけです。

私はこの方法を書きました:

import scala.concurrent.ExecutionContext.Implicits.global

private def sendApiRequest(method: String, params: Option[JsValue] = None)(implicit token: String): Future[JsObject] = {

if (concurrentRequests.get(token).isEmpty) {
  concurrentRequests += token -> 1
} else {
  concurrentRequests += token -> (concurrentRequests.get(token).get + 1)
}

println(s"$token: ${concurrentRequests.get(token).get}")

val request = WS.url(API_URL)
                .withMethod("POST")
                .withBody(Json.obj(
                  "application_id" -> clientId,
                  "method" -> method,
                  "token" -> token,
                  "param" -> params
                ))

request.execute().map(response => {
  val result = response.json.as[JsObject]
  if (!result.keys.contains("data")) {
    throw new Exception(result.toString())
  } else {
    result
  }
})
}

そして、このメソッドを使用するアクターがいて、数秒後に例外が発生します。

私の質問は次のとおりです。「実行モード」で機能の数を制御するにはどうすればよいですか? デフォルトの実行コンテキストではなく、別の実行コンテキストを使用する必要がありますか? 説明してください、または実行コンテキスト、スレッドなどの良い紹介をしてください

いちいち送信するのではなく、できるだけ早くリモートサービスから情報を取得したい

ありがとうございました!

4

2 に答える 2

0

私は解決策を見つけました:

private def sendApiRequest(method: String, params: Option[JsValue] = None): Future[JsObject] = {
val request = WS.url(API_URL)
  .withMethod("POST")
  .withBody(Json.obj(
  "application_id" -> clientId,
  "method" -> method,
  "token" -> token,
  "param" -> params
))

request.execute().map(response => {
  response.json.asOpt[JsObject] match {
    case Some(directResponse) =>
      (directResponse \ "error_code").asOpt[Int] match {
        case Some(error) if error == 52 || error == 506 =>
          sendApiRequest(method, params)
        case Some(error) => throw new UnknownApiException(error)
        case _ => Future.successful(directResponse)
      }
    case None => throw NotJsonResponseException
  }
}).flatMap(f => f)

}

error_code フィールドが 52 または 506 の json 応答を取得した場合 (つまり、現在 5 つ以上の要求が処理されていることを意味します)、同じ要求を再度作成して、Future[Future[Future[JsObject]]] を取得し、flatMap を実行します。 Future を 1 つだけ取得します :) このコードは機能し、必要なすべてのデータを 19 倍の速さで取得できます

于 2015-01-29T23:45:43.847 に答える
0

要求を調整するマネージャー オブジェクトまたはアクターを作成します。マネージャーにリクエストを送信すると、そのトークンのハンドラー オブジェクトまたはアクターが作成されるか、そのトークンの既存のハンドラーが使用可能な場合はそれが使用されます。

各ハンドラーには、カウンターとキューがあります。キューで要求を受信し、カウンターが 5 未満の場合はそれらを実行します。カウンターは、現在実行中の要求の数を記録します。リクエストが終了すると、カウンターが減少し、次のアイテムがキューから取り出されます。

メモリ リークを防ぐために、カウンターが 0 に達し、キューが空の場合、ハンドラーは自分自身をクリーンアップする必要があります。今後同じトークンを受信した場合、マネージャーはハンドラーを再作成します。

于 2015-01-29T01:21:31.793 に答える