我试图弄清楚如何使用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方面的任何专家都可以在这里提供帮助,那将非常棒。
答案 0 :(得分:0)
我从描述中假设,您想控制向下游生产元素的速度。而且,处理每个元素的成本也不同。
开箱即用的选项很少,可以控制流的速度。
可能您想使用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()
})
}
另一种选择是使用分组流程的组合,例如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()
})
}