当前位置: 首页 > 知识库问答 >
问题:

Scala使用多个Web服务和合并输出的惯用和最快方式

鲁钱明
2023-03-14

我有一个Scala应用程序,它使用多个数据源并合并组合输出,该应用程序并行调用多个HTTP调用并等待它们的结果,当所有问题都解决后,它将它们的输出合并到一个结果对象中,并将响应作为Scala Future发送回来。代码:

val providers = getProviders()
val futures = for (p <- providers) yield searchSource(p, req)
val result = waitAll(futures)
val emptyList = Option(ProductList(Vector.empty, ListSummary(0, 0, 0)))

result.map { x =>
  x.foldLeft(emptyList)((r, c) => {
    if (c.isSuccess) ProductList.merge(r, c.get) else r
  })
}

它首先获取提供程序字符串的列表,然后在 searchSource 中并行触发对每个提供程序的调用。

searchSource 函数本身返回 Future[Option[ProductList]]

该方法等待所有未来完成,为此调用waitAll函数:

  protected def waitAll[T](futures: Seq[Future[T]])(implicit ec: CustomExecutionContext): Future[Seq[Try[T]]] =
    Future.sequence(lift(futures))

  protected def lift[T](futures: Seq[Future[T]])(implicit ec: CustomExecutionContext): Seq[Future[Try[T]]] =
    futures.map(_.map { Success(_) }.recover { case t => Failure(t) })

在等待所有未来完成后,它将结果聚合到单个复合对象中,并将其作为未来返回。为此,我使用了foldLeft函数。

是否有任何“官方”的一元/惯用方法来解决此类问题,或者是否有此类用例的性能优化示例?

共有1个答案

单于阳
2023-03-14

当然这是一种常见的模式,使用猫效应IO,而不是未来确实有帮助(还有其他选择)。例如,您可以实现如下内容(为了清晰起见,我对类型进行了明确说明):

def searchSource(provider: String, request: Request[_]): IO[Option[ProductList]] = ???

val result: IO[List[Option[ProductList]]] = 
  providers.traverse[IO, Option[ProductList]](p => searchSource(p, req))

请注意,遍历本质上与映射后跟序列相同。然后,您可以在结果IO程序中执行任何操作(例如,映射它等),以将其转换为所需的最终结果。在程序结束时,您可以执行以下操作:

result.attempt.unsafeRunSync() //Either[Throwable, List[Option[ProductList]]]

有关错误处理,请查看 IO句柄错误使用方法。您可以在 searchSource 级别和/或结果级别处理错误,因为它们都是 IO

 类似资料:
  • 我在Scala上使用Play 2.5,我创建了一个类,可以多次调用外部web服务。 外部Web服务在某些条件下被调用并得到ok或nok的简单响应。如果可以,那么我应该更新内部对象状态,如果可以,我现在什么也不做。 这是我的类,它将String的列表作为参数,并返回要在控制器中处理的对象的Future列表。 是列表类型的列表,但我希望它只是一个简单的响应列表。 1)如何简化和纠正我的代码以获得响应列

  • 问题内容: 我试图将一个函数接收一个文件路径,确定它是什么,设置适当的标头,并像Apache一样提供服务。 我这样做的原因是因为在提供文件之前,我需要使用PHP处理有关请求的某些信息。 速度至关重要 virtual()不是一个选择 必须在用户无法控制Web服务器(Apache / nginx等)的共享托管环境中工作 到目前为止,这是我得到的: 问题答案: 我以前的回答是不完整的,没有很好的记录,这

  • 后端使用Spring Data+Spring MVC。 谢谢你。

  • 我已经使用程序youtube-dl下载了一个YouTube播放列表,我选择了单独下载视频和音频,我现在有一个文件夹充满了视频及其相应的音频,我希望与ffmpeg合并在一起。 我需要使用批处理脚本来执行此操作,但问题是youtube-dl在原始文件的标题之后添加了临时字母,因此视频与其对应的音频没有相同的名称,文件名如下所示: 如何使用windows批处理脚本和ffmpeg合并这些多个视频/音频文件

  • 我有一个Java的Play 2.1控制器,需要调用一个外部的webservice来获取一些数据。然后有了这个数据结果,我必须用n次调用调用另一个web服务,对应于第一个web service调用的n个结果。 对于性能问题,我想使用 promise 在单独的线程中进行 n 次调用。 所以我会有一个这样的循环: 如何使用异步API同步n个promise,然后在一个响应(所有结果的列表)中减少结果,然后

  • 我最近开始使用WebFlux,需要关于如何链接多个服务和聚合响应的建议。这4个服务及其响应POJO类似于以下示例: 以及4项服务的签名: 因此,需要为Flux中的每个响应1调用service2,为每个响应2调用service3。模型之间的关系是: 聚合的最终响应应类似于(JSON): 所以首先我需要调用Service1,然后为每个响应调用service2,然后为每个响应调用service3(由se