使用喷雾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)
我是这样做的,因为我不需要整个数据,只需要一些聚合。
如何解决此问题并将其完全保持异步?
答案 0 :(得分:6)
Akka ask timeout是通过firstCompletedOf实现的,所以定时器在ask初始化时启动。
你似乎正在做的是为每一行产生一个Future(在地图中) - 所以你的所有调用几乎同时执行。在初始化期货时,超时开始计算,但没有遗留给所有衍生的演员执行其工作的执行程序线程。因此要求超时。
我建议使用更灵活的方法 - 有点类似于使用iteratees或akka-streams:Work Pulling Pattern,而不是一次性处理“all。”。 (Github)
您提供已作为Epic
的迭代器。介绍一个Worker
演员,该演员将演出电话&一些逻辑。如果您生成N workers
那么,将同时处理最多N
行(并且处理管道可能涉及多个步骤)。通过这种方式,您可以确保不会使执行程序过载,并且不会发生超时。