Java 为什么使用Sink.asPublisher创建的发布服务器在被BroadcastHub使用时无法工作?

Java 为什么使用Sink.asPublisher创建的发布服务器在被BroadcastHub使用时无法工作?,java,akka-stream,Java,Akka Stream,我们有一个多组件应用程序,它在组件之间提供了一个反应流API。一些组件使用Akka流实现,其他组件使用例如反应堆 在一个组件中,我们注意到Streams没有处理任何消息,尽管提供的发布者提供了记录。我把这个问题归结为以下情况: Publisher-stringPublisher=Source .from(list.newArrayList(“你好”,“世界”,“!”)) .runWith(Sink.asppublisher(asppublisher.WITH_FANOUT)),物化器; Sour

我们有一个多组件应用程序,它在组件之间提供了一个反应流API。一些组件使用Akka流实现,其他组件使用例如反应堆

在一个组件中,我们注意到Streams没有处理任何消息,尽管提供的发布者提供了记录。我把这个问题归结为以下情况:

Publisher-stringPublisher=Source
.from(list.newArrayList(“你好”,“世界”,“!”))
.runWith(Sink.asppublisher(asppublisher.WITH_FANOUT)),物化器;
Source allMessages=Source
.fromPublisher(stringPublisher)
.toMat(BroadcastHub.of(String.class,256),Keep.right())
.run(物化器);
所有消息
.runForeach(System.out::println,materializer)
.toCompletableFuture()
.get();
一个组件提供发布服务器(它需要是发布服务器,因为API使用的是反应流API,而不是Akka Streams API)。此发布服务器是从另一个Akka Streams源创建的,并使用
Sink.asppublisher
转换为发布服务器

现在,当我们使用BroadcastHub从发布服务器开始具体化流时,根本不会处理任何记录

我在一个反应堆出版商身上也尝试了同样的方法:

Publisher-stringPublisher=Flux.fromIterable(Sink.asppublisher(asppublisher.WITH_FANOUT),物化器);
这正如预期的那样有效。不幸的是,我不能排除另一个组件从Akka流源创建其发布者的情况


有人知道哪里出了问题吗?

我现在知道如何解决它,如果我开始在mapMaterializedValue中使用BroadcastHub的结果源,它就会起作用:

Publisher-stringPublisher=Source
.from(list.newArrayList(“你好”,“世界”,“!”))
.runWith(Sink.asppublisher(asppublisher.WITH_FANOUT)),物化器;
来源
.fromPublisher(stringPublisher)
.ALSOMAT(BroadcastHub.of(String.class,256),Keep.right())
.mapMaterializedValue(源->源
.runWith(Sink.foreach(System.out::println,materialer))
.run(物化器)
.toCompletableFuture()
.get();
编辑: TL;DR:解释见:

这里发生的情况是,当您附加另一个流时,主流已经完成。有时,它可能足够快,可以在完成之前看到一些元素

--

因此,看起来BroadcastHub实际上在使用者连接到BroadcastHub创建的源之前删除了元素

文档中说它不会下降:

如果没有订户连接到此中心,则它不会丢弃任何元素,而是对上游生产商施加反压力,直到订户到达

事实上,这在大多数情况下都是正确的,但我发现在某些情况下,它的行为并不正确:

public void testBH3()引发ExecutionException、InterruptedException{
Publisher-stringPublisher=Source
.from(list.newArrayList(“你好”,“世界”,“!”))
.runWith(Sink.asppublisher(asppublisher.WITH_FANOUT)),物化器;
Source allMessages=Source
.fromPublisher(stringPublisher)
.toMat(BroadcastHub.of(String.class,256),Keep.right())
.run(物化器);
所有消息
.runForeach(System.out::println,materializer)
.toCompletableFuture()
.get();
}
public void repeat()引发ExecutionException、InterruptedException{
对于(int i=0;i<100;i++){
testBH3();
System.out.println(“----”);
}
}
这在100种情况中的3种情况下都有效。但以下情况在所有情况下都有效(我只是添加了一个节流阀以产生较慢的元件):

public void testBH3()引发ExecutionException、InterruptedException{
Publisher-stringPublisher=Source
.from(list.newArrayList(“你好”,“世界”,“!”))
.runWith(Sink.asppublisher(asppublisher.WITH_FANOUT)),物化器;
Source allMessages=Source
.fromPublisher(stringPublisher)
.节气门(1,持续时间秒(1))
.toMat(BroadcastHub.of(String.class,256),Keep.right())
.run(物化器);
所有消息
.runForeach(System.out::println,materializer)
.toCompletableFuture()
.get();
}

因此,在我看来,BroadcastHub有时会在没有接收器连接的情况下丢弃元素。

我进一步调查。它与Flux一起工作似乎是运气好。因为当我重复实验几百次时,它并不总是有效,只是比其他Akka Streams制作者更频繁。看起来我得到了一些东西广播中心出问题了。
public void testBH3() throws ExecutionException, InterruptedException {
    Publisher<String> stringPublisher = Source
        .from(Lists.newArrayList("Hello", "World", "!"))
        .runWith(Sink.asPublisher(AsPublisher.WITH_FANOUT), materializer);

    Source<String, NotUsed> allMessages = Source
        .fromPublisher(stringPublisher)
        .throttle(1, Duration.ofSeconds(1))
        .toMat(BroadcastHub.of(String.class, 256), Keep.right())
        .run(materializer);

    allMessages
        .runForeach(System.out::println, materializer)
        .toCompletableFuture()
        .get();
}