Akka Streams中平衡与广播扇出的区别

时间:2016-10-24 15:25:20

标签: scala akka akka-stream

我对Akka streams中的粉丝策略感到有些困惑,我读到了 Broadcast - (1个输入,N个输出)给定一个输入元素发送到每个输出,而Balance - (1个输入,N个输出)给定一个输入元素发送到其输出端口之一。

你能解释一下我吗:

  1. 如何与多个消费者合作?
  2. 短语“发出其输出端口之一”的含义
  3. 端口是否与下游相同?
  4. 'Balance'是否表示将输入流复制到一些输出分区
  5. “平衡是什么让图表分开,下游订户的多个实例被复制以处理交易量”是什么意思?

2 个答案:

答案 0 :(得分:5)

从文档...广播向每个消费者发出(发送)元素。余额仅发放给第一个可用的消费者。

broadcast

  

发出每个输入元素n个输出。

balance

  

将流扇出到多个流。每个上游元素都是   向第一个可用的下游消费者发放。

来自评论的编辑:

从你的要点,你应该制作两个averageCarrierDelay函数,每个ZF一个。然后你可以看到发送给每个元素的所有元素。

val averageCarrierDelayZ =
    Flow[FlightDelayRecord]
      .groupBy(30, _.uniqueCarrier)
        .fold(("", 0, 0)){
          (x: (String, Int, Int), y:FlightDelayRecord) => {
            println(s"Z Received Element: ${y}")
            val count = x._2 + 1
            val totalMins = x._3 + Try(y.arrDelayMins.toInt).getOrElse(0)
            (y.uniqueCarrier, count, totalMins)
          }
        }.mergeSubstreams


val averageCarrierDelayF =
    Flow[FlightDelayRecord]
      .groupBy(30, _.uniqueCarrier)
        .fold(("", 0, 0)){
          (x: (String, Int, Int), y:FlightDelayRecord) => {
            println(s"F Received Element: ${y}")
            val count = x._2 + 1
            val totalMins = x._3 + Try(y.arrDelayMins.toInt).getOrElse(0)
            (y.uniqueCarrier, count, totalMins)
          }
        }.mergeSubstreams

编辑2:为了检查将来的事情,我建议您使用流级的通用记录器,这样您就可以看到正在发生的事情。

def logElement[A](msg: String) = Flow[A].map { a => println(s"${msg} ${a}"); a }

执行此操作可以执行以下操作:

D ~> logElement[FlightDelayRecord]("F received: ") ~> F
D ~> logElement[FlightDelayRecord]("Z received: ") ~> Z

通过这种方式,您可以检查图表中您可能会或可能不会遇到的奇怪行为区域。

答案 1 :(得分:1)

正如其他人已经说过的那样,广播向所有输出端口发出输入,而平衡则根据背压将其输入发送到一个输出端口。

使用GraphStage时,需要选择要使用的输出端口。考虑这个例子:

val q1 = Source.queue[Int](10, OverflowStrategy.fail)
val q2 = Source.queue[Int](10, OverflowStrategy.fail)
GraphDSL.create(q1, q2)(Keep.both) { implicit b => (input1, input2) =>
  import GraphDSL.Implicits._

  val broadcast = b.add(Broadcast[Int](2))
  val balance = b.add(Balance[Int](2))

  val consumer1, consumer2, consumer3, consumer4 = b.add(Sink.foreach[Int](println))

  input1 ~> broadcast.in
  input2 ~> balance.in

  broadcast.out(0) ~> consumer1
  broadcast.out(1) ~> consumer2

  balance.out(0) ~> consumer3
  balance.out(1) ~> consumer4

  ClosedShape
}

这里我们将一个输入连接到一个广播舞台,一个输入连接到平衡阶段。然后我们将广播和平衡阶段的不同输出端口连接到相应的消费者。

在这种特殊情况下,当您运行流时,通过第一个输入的元素将传递给consumer1consumer2,因为广播阶段将其输入复制到其所有输出(和这是两个输出),来自第二个输入的元素将根据终端的速度(即consumer3的速度)在consumer4println之间均匀分布,因为{当函数执行很长时间时,{1}}背压。

请注意,我们已指定广播和平衡阶段各有2个端口(调用其工厂方法时),并且我们已指定连接到哪个消费者的输出端口。