将多个actor作为源附加到Akka流

时间:2018-03-10 00:09:08

标签: akka akka-stream

我知道有类似的问题已被提出:

How to attach multiple actors as sources to an Akka stream?

但我想做同样的事情,但我事先并不知道消息来源的数量。那么如何动态地将多个源添加到akka流中呢?

作为参考,这是另一个问题的接受答案,处理来源s1和s2:

 Source<Integer, ActorRef> src1 = Source.actorRef(100, OverflowStrategy.fail());
    Source<Integer, ActorRef> src2 = Source.actorRef(100, OverflowStrategy.fail());
    Sink<Integer, BoxedUnit> sink = Flow.of(Integer.class).to(Sink.foreach(System.out::println));

    RunnableFlow<List<ActorRef>> closed = FlowGraph.factory().closed(src1, src2, (a1, a2) -> Arrays.asList(a1, a2), (b, s1, s2) -> {
        UniformFanInShape<Integer, Integer> merge = b.graph(Merge.<Integer>create(2));
        b.from(s1).via(merge).to(sink);
        b.from(s2).to(merge);
    });

    List<ActorRef> stream = closed.run(mat);
    ActorRef a1 = stream.get(0);
    ActorRef a2 = stream.get(1);

但是在我的情况下,我会在新来源上线时添加来源,并在它们消失时将其删除。

谢谢!

1 个答案:

答案 0 :(得分:2)

如果您想动态地将源添加到正在运行的图形中,我认为MergeHub旨在实现这一目标:

https://doc.akka.io/docs/akka/current/stream/stream-dynamic.html#using-the-mergehub

// A simple consumer that will print to the console for now
Sink<String, CompletionStage<Done>> consumer = Sink.foreach(System.out::println);

// Attach a MergeHub Source to the consumer. This will materialize to a
// corresponding Sink.
RunnableGraph<Sink<String, NotUsed>> runnableGraph =
  MergeHub.of(String.class, 16).to(consumer);

// By running/materializing the consumer we get back a Sink, and hence
// now have access to feed elements into it. This Sink can be materialized
// any number of times, and every element that enters the Sink will
// be consumed by our consumer.
Sink<String, NotUsed> toConsumer = runnableGraph.run(materializer);

Source.single("Hello!").runWith(toConsumer, materializer);
Source.single("Hub!").runWith(toConsumer, materializer);

关于这些新图表在不再需要时关闭我认为你可以添加一个KillSwitch:

https://doc.akka.io/docs/akka/current/stream/stream-dynamic.html#uniquekillswitch

因此,动态附加新源将最终看起来像这样(未经测试):

UniqueKillSwitch killSwitch = Source.single("Hello!") // or whatever you want your source to be
    .viaMat(KillSwitches.single(), Keep.right())
    .toMat(toConsumer, Keep.left())
    .run(materializer);