使用喷雾客户端进行多次请求时akka超时

时间:2014-11-16 16:01:09

标签: scala spray spray-client

使用喷雾1.3.2和akka 2.3.6。 (akka仅用于喷雾) 我需要读取大文件,并为每一行发出一个http请求 我用迭代器逐行读取文件,并为每个项目发出请求。 它成功地运行了一些线路,但在某些时候它开始失败: akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://default/user/IO-HTTP#-35162984]] after [60000 ms]
我首先想到我重载了服务,所以我将“spray.can.host-connector.max-connections”设置为1.它运行得慢得多,但我也遇到了同样的错误。

代码如下:

import spray.http.MediaTypes._
val EdnType = register(
MediaType.custom(
  mainType = "application",
  subType = "edn",
  compressible = true,
  binary = false,
  fileExtensions = Seq("edn")))

val pipeline = (
  addHeader("Accept", "application/json")
  ~> sendReceive
  ~> unmarshal[PipelineResponse])

def postData(data: String) = {
  val request = Post(pipelineUrl).withEntity(HttpEntity.apply(EdnType, data))
  val responseFuture: Future[PipelineResponse] = pipeline(request)
  responseFuture
}

dataLines.map { d =>
  val f = postData(d)
  f.onFailure { case e => println("Error - "+e)} // This is where the errors are display
  f.map { p => someMoreLogic(d, p) }
}

aggrigateResults(dataLines)

我是这样做的,因为我不需要整个数据,只需要一些聚合。

如何解决此问题并将其完全保持异步?

1 个答案:

答案 0 :(得分:6)

Akka ask timeout是通过firstCompletedOf实现的,所以定时器在ask初始化时启动。

你似乎正在做的是为每一行产生一个Future(在地图中) - 所以你的所有调用几乎同时执行。在初始化期货时,超时开始计算,但没有遗留给所有衍生的演员执行其工作的执行程序线程。因此要求超时。

我建议使用更灵活的方法 - 有点类似于使用iteratees或akka-streams:Work Pulling Pattern,而不是一次性处理“all。”。 (Github

您提供已作为Epic的迭代器。介绍一个Worker演员,该演员将演出电话&一些逻辑。如果您生成N workers那么,将同时处理最多N行(并且处理管道可能涉及多个步骤)。通过这种方式,您可以确保不会使执行程序过载,并且不会发生超时。