我一直把从摆弄akka溪流的经验带到实用的水平,我遇到了麻烦。 下面是我尝试编写一个流式管道,从一个非常大的数据库表读取特定的行,然后为每一行发送http调用到外部Web服务,而不是将收到的响应插入到另一个表:
(数据库库为slick
,http客户端为播放框架)
val query = (catalogIndices joinLeft catalogSummeries on ((i, s) => i.productId === s.icecatId) filter (t => t._2.isEmpty) map (_._1)).result
val source = Source.fromPublisher(db.stream(query))
source
.buffer(5, OverflowStrategy.backpressure)
.mapAsync(5) { i =>
icecatService.fetchCatalog(i.productId, Languages.en, IcecatService.Contents.all)
}
.map { r =>
for {
g <- (r.json \ "data" \ "GeneralInfo").validate[GeneralInfo]
img <- (r.json \ "data" \ "Image").validate[Image]
} yield (g, img)
}
.collect {
case JsSuccess((g, img), _) => CatalogSummeryData(g.IcecatId, g.Title, g.Brand, g.ProductName, g.BrandPartCode,
g.GTIN, g.Category.CategoryID, g.Category.Name.Value, img.LowPic, img.ThumbPic)
}
.grouped(100)
.runForeach(s => db.run(catalogSummeries ++= s))
我可以说db作为上游非常快,而且那些Web服务调用真的很慢。如果我进一步增加mapAsync
方法的并行数,我的所有期货都会超时。
当我将项目的整个平台从Vagrant虚拟机迁移到我的Windows 10时,我的问题就出现了。现在,我的代码中的每一件事都运行得更快,但是这段流总是导致GC错误或内存不足错误等等。 。回到虚拟机我曾经让这段代码运行并成功传输了4000个结果。我应该如何调整此代码以使其执行?
编辑:另外我必须提一下,在我的Windows机器上,绝对不会在所有行都关闭之前插回行。
编辑:我收到了很多类型的错误,但这里有一个常见错误:
[ERROR] [SECURITY][09/27/2017 07:23:33.046] [application-scheduler-1]
[akka.actor.ActorSystemImpl(application)] Uncaught error from thread
[application-scheduler-1]: GC overhead limit exceeded, shutting down
ActorSystem[application]
java.lang.OutOfMemoryError: GC overhead limit exceeded
at akka.dispatch.AbstractNodeQueue.<init>(AbstractNodeQueue.java:32)
at akka.actor.LightArrayRevolverScheduler$TaskQueue.<init (LightArrayRevolverScheduler.scala:304)
at akka.actor.LightArrayRevolverScheduler$$anon$4.nextTick(LightArrayRevolverScheduler.scala:269)
at akka.actor.LightArrayRevolverScheduler$$anon$4.run(LightArrayRevolverScheduler.scala:235)
at java.lang.Thread.run(Thread.java:748)