如何使扇出akka-streams并发处理

时间:2017-10-02 23:43:09

标签: scala concurrency akka akka-stream

我试图使用Akka Streams同时处理一系列依赖流。

这样的事情:

val concurrency = 2
Source(
  (1 to 5).toStream.map(i => {
    println(s"1: Emitting $i")
    i.toString
  }))
  .mapAsyncUnordered(concurrency)(s => getNextStream(s, 25))
  .mapConcat(identity)
  .mapAsyncUnordered(concurrency)(out => getNextStream(out.x, 50))
  .mapConcat(identity)
  .mapAsyncUnordered(concurrency)(out => getNextStream(out.x, 100))
  .mapConcat(identity)
  .map(x => println(s"4: Received $x after ${System.currentTimeMillis() - start}"))
  .runWith(Sink.ignore)

我的问题是它似乎没有同时运行。更改concurrency变量不会超出2。我怀疑mapConcat正在序列化处理,但我不确定。

可以在此处找到问题的完整,可运行的示例:https://github.com/realrunner/akka-stream-example

目前,代码需要11秒才能完成。我可以使用原始Actors轻松地将其削减,而无需正确处理背压。关于如何使其更加并发的任何想法?

1 个答案:

答案 0 :(得分:1)

这些getNextStream来电中的每一个都会出来并使用ask来对抗一个(吨)演员。请记住,actor以序列化方式处理传入的消息。

现在处理邮件时,您使用Thread.sleep来阻止该角色。在Akka内部通常不鼓励阻止 - 请参阅docs的这一点。

根据您的演员的真实行为,您可以使用after模式以非阻塞方式模拟长时间处理(请参阅docs),或者如果阻止 需要 - 但是双重,三重检查 - 您可以阻止专用调度员(如here所述)。