我正在尝试使用具有以下特征的Project Reactor Flux
作为示例:
replay()
时的历史记录有限,因此如果其中一个订阅者速度太慢,则会遗漏某些项目。然后我编写了这个样本:
import java.time.Duration;
import reactor.core.publisher.ConnectableFlux;
import reactor.core.publisher.Flux;
import reactor.core.scheduler.Schedulers;
public class FluxTest {
public static void main(String[] args) {
final ConnectableFlux<Integer> publisher = Flux.range(1, 20)
.delayElements(Duration.ofSeconds(1))
.replay(8);
publisher.publishOn(Schedulers.newSingle("fast"))
.subscribe(i -> {
System.out.println("Fast subscriber - Received " + i);
sleep(1);
});
publisher.publishOn(Schedulers.newSingle("slow"))
.subscribe(i -> {
System.out.println("Slow subscriber - Received " + i);
sleep(5);
});
publisher.connect();
}
private static void sleep(int seconds) {
try {
Thread.sleep(seconds * 1000L);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
根据replay(int history)
方法的the documentation,我希望在几秒钟之后,第二个消费者(慢速消费者)会开始失去音轨,但事实并非如此。请参阅控制台输出的这一部分作为示例:
...
Fast subscriber - Received 14
Fast subscriber - Received 15
Slow subscriber - Received 4
Fast subscriber - Received 16
Fast subscriber - Received 17
我预计慢速订阅者无法接收4
,因为该元素不再是历史记录(15 - 8 = 7,应该是最后一个)。
请注意,如果我使用方法replay(8, Duration.ofSeconds(8))
,那么我会得到我期望的结果:
...
Fast subscriber - Received 14
Fast subscriber - Received 15
Slow subscriber - Received 8
Fast subscriber - Received 16
Fast subscriber - Received 17
我想我在这里缺少一些重要的东西,但我不知道它是什么。
答案 0 :(得分:1)
replay(8)
能够重播8个元素,这些元素在订阅订阅之前发出。对于之后进入的元素,它们直接转发给订户。在这里,您在连接之前订阅slow
,因此重放缓冲区的大小并不重要。
您的慢速订阅者在专用线程上休眠,所以会发生publishOn
确实接收到所有数据,将其置于内部Queue
并在slow
线程上自行调度排空该队列,在每次迭代中被阻塞5秒的排水循环中。
尽管如此,运营商已经看到并且能够处理所有数据。