2015-01-28 2 views
0

나는 플레이! http 요청을 보내서 다른 서버와 통신하는 스칼라 응용 프로그램입니다. 이 시스템에는 한계가 있습니다. 단 하나의 토큰에 대해 5 개의 HTTP 요청 만 수행 할 수 있습니다.스칼라, 선물, WS 라이브러리, Api

이 나는이 방법을 서면으로 작성했습니다 :

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

당신은 HTTP를 처리하는 코드를 표시해야합니다 의뢰. – Salem

답변

0

요청을 조정할 관리자 개체 또는 액터를 만듭니다. 매니저에 요청을 제출하면 해당 토큰에 대한 핸들러 오브젝트 또는 액터를 작성하거나 사용 가능한 경우 해당 토큰에 대한 기존 핸들러를 사용합니다.

각 처리기에는 카운터와 대기열이 있습니다. 대기열에서 요청을 수신하고 카운터가 < 인 경우 실행합니다. 5. 카운터는 현재 실행중인 요청 수를 기록합니다. 요청이 완료되면 카운터가 감소하고 다음 항목이 대기열에서 빠져 나옵니다.

메모리 누수를 방지하려면 카운터가 0이되고 큐가 비어 있으면 처리기가 스스로 정리해야합니다. 나중에 동일한 토큰이 다시 수신되면 관리자는 핸들러를 다시 작성합니다.

+0

그 아이디어에 대해 생각해 봤지만,이 구현은 내 앱 코드를 복잡하게 만듭니다. 감사합니다 –

+0

예, 확실히 더 복잡합니다! –

0

I 발견 용액 : 전 (5 개 이상의 요구가 지금은 처리되는 것을 의미) ERROR_CODE 필드 52 또는 506 JSON 응답을 받으면

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) 

} 

제가 다시 동일한 요청을하고 그래서 미래를 얻을 [미래 [미래 [JsObject]]] 그리고 난 flatMap 하나만 미래를 얻으려면 :)이 코드는 작동하고 내가 19x 배속에서 필요한 모든 데이터를 가지고있다

+0

이것이 자신의 서버가 아닌 경우 실패한 요청 후에 지연을 추가해야합니다. 즉시 재 시도하면 서버가 스팸됩니다. –

+0

예, 내 서버가 아닙니다. 요청을 다시 시도하기 전에 Thread.sleep (1000)을 넣으시겠습니까? –

+1

예, Thread.sleep이거나, 더 효율적으로 만들고 싶다면 play.libs.Akka.system.scheduler를 사용하여 콜백을 예약하십시오. –