如何使用Akka stream Flow.batch对源中发出的多个元素进行批处理

如何使用Akka stream Flow.batch对源中发出的多个元素进行批处理,akka,reactive-programming,akka-stream,Akka,Reactive Programming,Akka Stream,我正在使用以下代码来测试akka stream Flow.batch的行为,但不知何故,我无法找出为什么结果不是我所期望的: Source(1 to 20) .map(x => { println(s"received: ${x}") x }) .batch(max=3, first => first.toString) {(batch, elem) => { batch + "," + elem }} .runWith(Sink

我正在使用以下代码来测试akka stream Flow.batch的行为,但不知何故,我无法找出为什么结果不是我所期望的:

  Source(1 to 20)
  .map(x => {
    println(s"received: ${x}")
    x
  })
  .batch(max=3, first => first.toString) {(batch, elem) => {
    batch + "," + elem
  }}
  .runWith(Sink.foreach(x=>{
    Thread.sleep(4000)
    println("Out:" + x)
  }))
以下是输出:

收到:1
收到:2
收到:3
收到:4
输出:1,2,3
收到:5
输出:4
收到:6
输出:5
收到:7
输出:6
收到:8
输出:7
收到:9
输出:8
收到:10
输出:9
收到:11
外出时间:10
收到:12
输出:11
.... 等等。。。。
收到:19
外出:18
收到:20
外出:19
输出:20

这里有几点我无法理解:

  • 首先,我的水槽慢多了。我预计在排放到下游之前,该项目将被分批处理,例如:Out:1,2,3;输出:4,5,6;结果:7,8;输出:9、10、11等等。相反,它只被批处理一次(1,2,3),但随后元素被一个接一个地发出,而不是被批处理
  • 为什么我在正确的开头收到了4个项目(收到:1,…,收到:4),而实际上,我只设置了max=3(批处理(max=3))
  • 因为源比汇快得多。我希望元素的发射速度应该快得多,例如:received:7,received:8,received:9;然后出来:7,8,9,;但事实上,它只是在Sink的println函数执行之后才偶尔一个接一个地发出
我已尝试将map更改为mapAsync,但其行为仍然不是我想要的:

  .mapAsync(1)(x => {
    println(s"received: ${x}")
    Future.successful(x)
  })

谢谢。

代码中没有异步边界,它将在单个线程上运行。基本上,当您的Thread.sleep()执行时,在此设置中不会发生任何其他进展,即批处理无法发生(因为线程在Thread.sleep上被阻塞)。如果您有这样的设置,那么您可以使用grouped()而不是batch,或者groupedWithin()。如果仍要尝试batch(),请尝试节流阶段,而不是添加睡眠。节流阀不会阻塞螺纹,因此不会影响上游进度(批处理)