2015-06-30 6 views
1

Я хочу настроить клиент http-клиента таким образом, чтобы контролировать максимальное количество запросов, отправленных на сервер. Мне нужно это, потому что сервер, который я отправляю запросы, блокирует меня, если отправлено более 2 запросов. Я получаюСпрей http-клиент и тысячи запросов

akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://smallTasks/user/IO-HTTP#151444590]] after [15000 ms] 
akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://smallTasks/user/IO-HTTP#151444590]] after [15000 ms] 
akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://smallTasks/user/IO-HTTP#151444590]] after [15000 ms] 
akka.pattern.AskTimeoutException: Ask timed out on 

Мне нужно отправить тысячи запросов, но я заблокирован после получения ответов от ~ 100 запросов.

У меня есть этот метод:

implicit val system = ActorSystem("smallTasks") 
    implicit val timeout = new Timeout(15.seconds) 

    import system.dispatcher 

    def doHttpRequest(url: String): Future[HttpResponse] = { 
    (IO(Http) ? HttpRequest(GET, Uri(url))).mapTo[HttpResponse] 
    } 

И здесь я поймать ответы и повторить попытку, если это не удается (рекурсивно):

def getOnlineOffers(modelId: Int, count: Int = 0): Future[Any] = { 

    val result = Promise[Any]() 

    AkkaSys.doHttpRequest(Market.modelOffersUrl(modelId)).map(response => { 
     val responseCode = response.status.intValue 
     if (List(400, 404).contains(responseCode)) { 
     result.success("Bad request") 
     } else if (responseCode == 200) { 
     Try { 
      Json.parse(response.entity.asString).asOpt[JsObject] 
     } match { 
      case Success(Some(obj)) => 
      Try { 
       (obj \\ "onlineOffers").head.as[Int] 
      } match { 
       case Success(offers) => result.success(offers) 
       case _ => result.success("Can't find property") 
      } 

      case _ => result.success("Wrong body") 
     } 
     } else { 
     result.success("Unexpected error") 
     } 
    }).recover { case err => 
     if (count > 5) { 
     result.success("Too many tries") 
     } else { 
     println(err.toString) 
     Thread.sleep(200) 
     getOnlineOffers(modelId, count + 1).map(r => result.success(r)) 
     } 
    } 

    result.future 

    } 

Как сделать это правильно? Может быть, мне нужно настроить диспетчера akka?

+0

Что вы хотите сделать, если достигнуто максимальное количество одновременных соединений? Отклонить запрос? Подождите с заданным таймаутом? –

+0

Мне нужно собрать информацию для каждой модели, поэтому, если запрос не удается, я хочу повторить этот неудачный запрос с таймаутом. Я уже сделал это (см. Thread.sleep (200)). Он отлично работает в течение 10 - 15 секунд, после этого времени я получаю много Akka, чтобы исключить тайм-аут в консоли. Я думаю, что это происходит, потому что у меня 10000 моделей, и все они запускаются одновременно. Я ищу способ заставить http-клиента отправлять только 2 или 3 запроса за раз, а не отправлять другой запрос, пока старый запрос без ответа –

ответ

1

вы можете использовать http://spray.io/documentation/1.2.2/spray-client/ и написать вам личный трубопровод

val pipeline: Future[SendReceive] = 
     for (
     Http.HostConnectorInfo(connector, _) <- 
      IO(Http) ? Http.HostConnectorSetup("www.spray.io", port = 80) 
    ) yield sendReceive(connector) 

    val request = Get("/segment1/segment2/...") 
    val responseFuture: Future[HttpResponse] = pipeline.flatMap(_(request)) 

получить HttpResponse

import scala.concurrent.Await 
import scala.concurrent.duration._ 
val response: HttpResponse = Aweit(responseFuture, ...) 

конвертировать

import spray.json._ 
response.entity.asString.parseJson.convertTo[T] 

проверить

Try(response.entity.asString.parseJson).isSuccess 

слишком много скобок. В scala вы можете написать это короче