我在akka流中实现了一个自定义组件,它将元素作为输入,组合并根据键合并它们,并通过十几个出口中的一个发送出去。您可以将此组件视为一种GroupBy组件,它不会将流分为子流,而是实际流。除了对传入元素进行分区之外,它还将它们合并为一个元素,即组件内部发生了一些缓冲,使得1个元素并不一定意味着通过插座输出1个元素。
以下是所述组件的简化实现。
class CustomGroupBy[A,B](k: Int, f: A => Int) extends GraphStage[FlowShape[B, B]] {
val in = Inlet[A]("CustomGroupBy.in")
val outs = (0 until k).map(i => Outlet[B](s"CustomGroupBy.$i.out"))
override val shape = new AmorphousShape(scala.collection.immutable.Seq(in), outs)
/* ... */
}
我现在将该组件的每个插座连接到不同的接收器并将所有这些接收器的物化值组合起来。
我已尝试使用图形DSL进行了一些操作,但还没有完全成功地使用它。有人会非常友好地为我提供一个片段来指导我或指出我正确的方向吗?
提前致谢!
答案 0 :(得分:4)
答案 1 :(得分:1)
您可能想要akka.stream.scaladsl.Partition[T](outputPorts: Int, partitioner: T ⇒ Int)
stage。
编辑:
要连接所有端口并保留具体化值,您必须将阶段作为GraphDSL.create
方法的参数。
这允许您为物化值定义组合器,并将阶段添加到GraphDSLBuilder
,作为最后一个参数的参数。请注意,这个重载的create
方法不接受varargs参数,因此可能无法以这种方式处理14个不同的阶段。
假设您的阶段有一些名称,以下是我将如何实现它,在3个输出的情况下:
val runnable = RunnableGraph.fromGraph(
GraphDSL.create(
source, customGroupBy, sink1, sink2, sink3)(combiner) { //the combiner is the function to combine the materialized values
implicit b => //this is the builder, needed as implicit to make the connections
(src, cgb, s1, s2, s3) => //here are the stages added to the builder
import GraphDSL.Implicits._
src.out ~> cgb.in
List(s1, s2, s3).map(_.in).zip(cgb.outlets).foreach{
case (in, out) => in ~> out
}
ClosedShape
}
)
)
请记住,如果您不需要其中一个阶段'物化价值,您可以通过val cgb = b.add(customGroupBy)