Scala,期货,WS库,Api

时间:2015-01-28 18:03:22

标签: scala concurrency playframework concurrent.futures

我玩了!在Scala应用程序上通过发送http请求与另一台服务器通信。该系统有限制:只有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
  }
})
}

还有一些演员使用这种方法,几秒后我就会得到那个例外。

我的问题是:我如何控制'RUNNING MODE'中的功能数量?可能是我应该使用另一个执行上下文而不是默认的一个?请解释我,或者对执行上下文,线程等进行详细介绍

我希望尽快从远程服务获取信息,而不是逐个发送

谢谢!

2 个答案:

答案 0 :(得分:0)

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

每个处理程序都有一个计数器和一个队列。它接收队列上的请求并在计数器<1时运行它们。 5.计数器记录当前正在运行的请求数。请求完成后,计数器将减少,下一个项目将从队列中删除。

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

答案 1 :(得分: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只获得一个未来:)这段代码有效,我所需的所有数据都快了19倍