Akka-stream是否有状态运作?

时间:2019-09-06 03:21:45

标签: akka-stream

我试图弄清楚如何使用akka-stream执行以下有状态操作:

假设我通过该流向其中释放了一组元素e,其中包含任意一组元素a。

我想根据接收到的元素e的数量表示的元素a的总量,对通过下游的元素e的数量进行速率限制。

例如4

传入流

-> e1(a1e1)

-> e2(a1e2,a2e2)

-> e3(a1e3)

-> e4(a1e4,a2e4)

-> e5(a1e5,a2e5)

会发出

group1 [e1,e2,e3]

group2 [e4,e5]

最后,应按groupWithin中的时间进行计时。如果经过了一定的时间,那么就放出任何东西。

像statefulmapContact之类的声音可能是要看的东西,但我不确定。

如果akka-stream方面的任何专家都可以在这里提供帮助,那将非常棒。

1 个答案:

答案 0 :(得分:0)

我从描述中假设,您想控制向下游生产元素的速度。而且,处理每个元素的成本也不同。

开箱即用的选项很少,可以控制流的速度。

  1. 可能您想使用throttle。它控制流的吞吐量。

      油门-将吞吐量限制为每个时间单位特定数量的元素,或每个时间单位特定的总成本,其中必须提供一个函数来计算每个元素的单个成本。       导入java.time.LocalDateTime

    import akka.actor.ActorSystem
    import akka.stream.ActorMaterializer
    import akka.stream.scaladsl.Source
    
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent.duration._
    import scala.util.Random
    
    object ThrottleExample extends App {
    
        implicit val sys: ActorSystem = ActorSystem()
        implicit val mat: ActorMaterializer = ActorMaterializer()
    
        case class E(as: Seq[Int])
    
        val f = Source(1 to 20)
            .map(_ => Random.nextInt(7))
            .map(len => E((1 to len).map(_ => 1)))
            .throttle(5, 1.second, _.as.size)
            .runForeach(e => {
                println(s"${LocalDateTime.now()} -> $e")
            })
    
        f.onComplete(_ => {
            mat.shutdown()
            sys.terminate()
        })
    }
    
  2. 另一种选择是使用分组流程的组合,例如groupedWeightedWithin(使用元素进行批处理,以达到某个批处理成本或所花费的时间)或batchWeighted(如果下游速度较慢,则进行批处理/汇总)以及简单的throttle

      

    groupedWeightedWithin-将时间流分成在时间窗口内接收到的元素组,或者受元素权重限制(无论先发生什么)。


      batchWeighted-只要存在背压并且尚未达到最大权重批处理元素,就可以通过将传入元素和摘要传递到聚合函数中来降低下游速度。

    import java.time.LocalDateTime
    
    import akka.actor.ActorSystem
    import akka.stream.ActorMaterializer
    import akka.stream.scaladsl.Source
    
    import scala.concurrent.ExecutionContext.Implicits.global
    import scala.concurrent.duration._
    import scala.util.Random
    
    object GroupedWithingExample extends App {
    
        implicit val sys: ActorSystem = ActorSystem()
        implicit val mat: ActorMaterializer = ActorMaterializer()
    
        case class E(as: Seq[Int])
    
        val f = Source(1 to 20)
            .map(_ => Random.nextInt(5))
            .map(len => E((1 to len).map(_ => 1)))
            .groupedWeightedWithin(7, 1.second)(_.as.length)
            .throttle(1, 1.second)
            .runForeach(e => {
                println(s"${LocalDateTime.now()} -> $e")
            })
    
        f.onComplete(_ => {
            mat.shutdown()
            sys.terminate()
        })
    }