在Akka流中创建来自Future的背压

时间:2016-10-07 04:17:53

标签: scala akka akka-stream

我对Akka流和流一般是新手,所以我可能在概念层面上完全误解了某些东西,但是有什么方法可以创建背压直到未来结算?基本上我想做的就是这样:

object Parser {
    def parseBytesToSeq(buffer: ByteBuffer): Seq[ExampleObject] = ???
}

val futures = FileIO.fromPath(path)
  .map(st => Parser.parseBytesToSeq(st.toByteBuffer))
  .batch(1000, x => x)(_ ++ _)
  .map(values => doAsyncOp(values))
  .runWith(Sink.seq)

def doAsyncOp(Seq[ExampleObject]) : Future[Any] = ???

从文件中读取字节并将其流式传输到解析器,解析器将发出SeqExampleObject个,并将这些字节流式传输到返回Future的异步操作。我希望这样做,以便在Future结算之前,流的其余部分得到反压,然后在Future解析后恢复,将另一个Seq[ExampleObject]传递给doAsyncOp,这将恢复背压等等。

现在我使用了这个:

Await.result(doAsyncOp(values), 10 seconds)

但我的理解是,这会锁定整个线程并且很糟糕。有没有更好的方法呢?

如果有帮助,那么大局是我试图用Jawn解析一个非常大的JSON文件(太大而不适合内存),然后将对象传递给ElasticSearch作为索引它们被解析了--ElasticSearch有一个包含50个待处理操作的队列,如果溢出则开始拒绝新对象。

1 个答案:

答案 0 :(得分:10)

这很容易。您需要使用mapAync:)

val futures = FileIO.fromPath(path)
  .map(st => Parser.parseBytesToSeq(st.toByteBuffer))
  .batch(1000, x => x)(_ ++ _)
  .mapAsync(4)(values => doAsyncOp(values))
  .runWith(Sink.seq)

其中4是并行级别。