0

我有玩!在通过发送 http 请求与另一台服务器通信的 Scala 应用程序上。该系统有局限性:一个令牌只能同时处理 5 个 http 请求。

我写了这个方法:

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

创建一个管理器对象或参与者来协调请求。当您向管理器提交请求时,它会为该令牌创建一个处理程序对象或参与者,或者使用该令牌的现有处理程序(如果可用)。

每个处理程序都有一个计数器和一个队列。它接收队列上的请求并在计数器 < 5 时运行它们。计数器记录当前正在运行的请求数。当请求完成时,计数器减少并且下一个项目被拉出队列。

为防止内存泄漏,如果计数器达到 0 且队列为空,处理程序应自行清理。如果将来再次收到相同的令牌,管理器将再次重新创建处理程序。

于 2015-01-29T01:21:31.793 回答
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 :) 这段代码有效,我以 19 倍的速度获得所需的所有数据

于 2015-01-29T23:45:43.847 回答