我玩了!在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'中的功能数量?可能是我应该使用另一个执行上下文而不是默认的一个?请解释我,或者对执行上下文,线程等进行详细介绍
我希望尽快从远程服务获取信息,而不是逐个发送
谢谢!
答案 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倍