[英]Akka-streams backpressure on broadcast with async processing
我很難理解akka-stream在進行廣播時,如果一個分支的廣播占用了圖表中的大量時間(異步),則akka-stream是否會對Source施加反壓。
我嘗試了buffer
和batch
以查看是否在源上施加了任何反壓,但它看起來並不像它。 我也嘗試了刷新System.out
但它沒有任何改變。
object Test extends App {
/* Necessary for akka stream */
implicit val system = ActorSystem("test")
implicit val materializer: ActorMaterializer = ActorMaterializer()
val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
import GraphDSL.Implicits._
val in = Source.tick(0 seconds, 1 seconds, 1)
in.runForeach(i => println("Produced " + i))
val out = Sink.foreach(println)
val out2 = Sink.foreach[Int]{ o => println(s"2 $o") }
val bcast = builder.add(Broadcast[Int](2))
val batchedIn: Source[Int, Cancellable] = in.batch(4, identity) {
case (s, v) => println(s"Batched ${s+v}"); s + v
}
val f2 = Flow[Int].map(_ + 10)
val f4 = Flow[Int].map { i => Thread.sleep(2000); i}
batchedIn ~> bcast ~> f2 ~> out
bcast ~> f4.async ~> out2
ClosedShape
})
g.run()
}
我希望在運行程序時在控制台中看到“ Batched ...”(批處理...),並且由於f4的處理速度不夠快而使它暫時卡住。 目前,由於連續生成數字並且不進行批處理,因此這些行為均未達到預期的效果。
編輯:我注意到一段時間后,批處理消息開始在控制台中打印出來。 我仍然不知道為什么它不會很快發生,因為第一個元素應該發生背壓
解釋此行為的原因是由akka在設置異步邊界時引入的內部緩沖區。
內部緩沖區,在使用異步運算符時作為優化引入。
雖然流水線通常會提高吞吐量,但實際上,將元素傳遞到異步(並因此穿過線程)邊界是很昂貴的。 為了攤銷此成本,Akka Streams在內部使用了窗口化的批量反壓策略。 之所以要窗口化,是因為與Stop-And-Wait協議相反,多個元素可能與請求元素同時“進行中”。 這也是批處理的,因為一旦從窗口緩沖區中刪除了一個元素,就不會立即請求一個新元素,而在多個元素被耗盡之后,會請求多個元素 。 這種批處理策略減少了通過異步邊界傳播背壓信號的通信成本。
我知道這是玩具流,但是如果您解釋目標是什么,我會盡力幫助您。
您需要mapAsync
而不是async
val g = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder: GraphDSL.Builder[NotUsed] =>
import akka.stream.scaladsl.GraphDSL.Implicits._
val in = Source.tick(0 seconds, 1 seconds, 1).map(x => {println(s"Produced ${x}"); x})
val out = Sink.foreach[Int]{ o => println(s"F2 processed $o") }
val out2 = Sink.foreach[Int]{ o => println(s"F4 processed $o") }
val bcast = builder.add(Broadcast[Int](2))
val batchedIn: Source[Int, Cancellable] = in.buffer(4,OverflowStrategy.backpressure)
val f2 = Flow[Int].map(_ + 10)
val f4 = Flow[Int].mapAsync(1) { i => Future { println("F4 Started Processing"); Thread.sleep(2000); i }(system.dispatcher) }
batchedIn ~> bcast ~> f2 ~> out
bcast ~> f4 ~> out2
ClosedShape
}).run()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.