Reactor Flux重放(int history)方法无法按预期工作

时间:2018-04-02 15:09:47

标签: reactive-programming project-reactor

我正在尝试使用具有以下特征的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

我想我在这里缺少一些重要的东西,但我不知道它是什么。

1 个答案:

答案 0 :(得分:1)

replay(8)能够重播8个元素,这些元素在订阅订阅之前发出。对于之后进入的元素,它们直接转发给订户。在这里,您在连接之前订阅slow,因此重放缓冲区的大小并不重要。

您的慢速订阅者在专用线程上休眠,所以会发生publishOn确实接收到所有数据,将其置于内部Queue并在slow线程上自行调度排空该队列,在每次迭代中被阻塞5秒的排水循环中。

尽管如此,运营商已经看到并且能够处理所有数据。