您可以考虑将调用批处理到第二个 Web 服务中,并且仅在前一个批处理完成后才继续执行后续批处理。该方法可能如下所示:
val fut = for {
ids <- WS.url(url1).get.map(res => res.body.split("").grouped(batchSize).toList)
responses <- processBatches(ids)
} yield responses
fut onComplete{
case Success(responses) => //handle responses
case Failure(ex) => //handle fail
}
def processBatches(batches:List[Array[String]]) = {
val prom = Promise[List[Response]]()
var trys = List[List[Response]]()
def doProcessBatch(remainingBatches:List[Array[String]]) {
val batch = remainingBatches.head
val futs = batch.map(id => WS.url(url2 + id).get).toList
Future.sequence(futs) onComplete{ tr =>
val list = tr.getOrElse(List()) //add better error handling here
trys = list :: trys
if (remainingBatches.size > 1) doProcessBatch(remainingBatches.tail)
else prom.success(trys.flatten)
}
}
doProcessBatch(batches)
prom.future
}
野兔的想法是点击第一个服务以获取 ids 列表,然后将其分解为由您选择的某个批次大小确定的批次。然后,处理这些批次,将 batchSize 数量的并发调用发送到第二个 ws 调用,等到所有都完成后再移动到下一个批次。完成后,您将拥有Future
一个List[Response]
代表对第二个服务进行的所有调用的一个。这不是生产就绪代码,因为它需要更好地处理故障(在这种情况下我只是返回一个空列表)。它也可能需要在此行上链接对recover
after的调用:get
val futs = batch.map(id => WS.url(url2 + id).get).toList
以防止批次中的一次失败导致您丢失该批次的其余结果,但我将把这些东西留给您。我只是想向您展示一个高级概念,用于将调用批处理到第二个服务中,以不被调用淹没。