将通量/发布者/订阅者连接到连续生成器

时间:2019-01-23 12:24:40

标签: java reactive-programming project-reactor

我有一个类,可以连续生成和存储新数据值(使用线程池)。我想为客户端代码(“订户”)提供一种手段来利用(连接)新数据值的序列。但是,如果我的班级没有客户端,或者所有客户端都已从序列中读取完,我希​​望它继续生成和存储新值而不停止。当客户端连接到该序列时,它将接收新生成的值,但不会接收过去生成的值。哪个Project Reactor类(或多个类)适合执行此操作?

我想我需要使用Flux来表示新值的序列,但是要使用哪个Flux类(或工厂方法)?

1 个答案:

答案 0 :(得分:1)

使用DirectProcessor

据我了解,无论上游是否有订阅者,需要的是订阅上游功能的能力。

DirectProcessor的支持下可以实现。由于ProcessorPublisherSubscriber的组合,因此它可以“上游”运行并连续收听传入的信号。同时,DirectProcessor启用消息多路分解,或仅向所有可用的下游订户(如果他们正在监听)广播消息。

例如,让我们考虑以下代码示例:

Flux<Long> intervalFlux = Flux.interval(Duration.ofMillis(500)).log("upstream");
DirectProcessor processor = DirectProcessor.create();

intervalFlux.subscribe(processor);

Thread.sleep(2000);

Disposable downstream1 = processor.log("downstream1")
                                  .subscribe();

Thread.sleep(1000);

downstream1.dispose();

Thread.sleep(1000);

Disposable downstream2 = processor.log("downstream2")
                                  .subscribe();
Thread.sleep(2000);

我们可以看到,我们使用处理器订阅了上游,因此间隔Flux开始生成数据。然后,我们订阅了processor并等待了1秒钟,因此log("upstream")运算符通常应记录下下游事件1和6观察到两个事件。之后,我们取消了订阅,因此downstream1订阅者应该停止观察任何事件,但是log("upstream")应该仍然观察间隔。然后,在另一个暂停之后,我们与另一个downstrea2订阅者订阅了该流,该订阅者应观察到另外四个事件。

上述代码的一般输出如下:

2019-01-23 15:09:04,246 INFO upstream [main] onSubscribe(FluxInterval.IntervalRunnable)
2019-01-23 15:09:04,249 INFO upstream [main] request(unbounded)
2019-01-23 15:09:04,757 INFO upstream [parallel-1] onNext(0)
2019-01-23 15:09:05,252 INFO upstream [parallel-1] onNext(1)
2019-01-23 15:09:05,751 INFO upstream [parallel-1] onNext(2)
2019-01-23 15:09:06,252 INFO upstream [parallel-1] onNext(3)
2019-01-23 15:09:06,258 INFO downstream1 [main] onSubscribe(DirectProcessor.DirectInner)
2019-01-23 15:09:06,258 INFO downstream1 [main] request(unbounded)
2019-01-23 15:09:06,754 INFO upstream [parallel-1] onNext(4)
2019-01-23 15:09:06,755 INFO downstream1 [parallel-1] onNext(4)
2019-01-23 15:09:07,254 INFO upstream [parallel-1] onNext(5)
2019-01-23 15:09:07,254 INFO downstream1 [parallel-1] onNext(5)
2019-01-23 15:09:07,263 INFO downstream1 [main] cancel()
2019-01-23 15:09:07,755 INFO upstream [parallel-1] onNext(6)
2019-01-23 15:09:08,255 INFO upstream [parallel-1] onNext(7)
2019-01-23 15:09:08,265 INFO downstream2 [main] onSubscribe(DirectProcessor.DirectInner)
2019-01-23 15:09:08,265 INFO downstream2 [main] request(unbounded)
2019-01-23 15:09:08,755 INFO upstream [parallel-1] onNext(8)
2019-01-23 15:09:08,756 INFO downstream2 [parallel-1] onNext(8)
2019-01-23 15:09:09,255 INFO upstream [parallel-1] onNext(9)
2019-01-23 15:09:09,256 INFO downstream2 [parallel-1] onNext(9)
2019-01-23 15:09:09,751 INFO upstream [parallel-1] onNext(10)
2019-01-23 15:09:09,751 INFO downstream2 [parallel-1] onNext(10)
2019-01-23 15:09:10,255 INFO upstream [parallel-1] onNext(11)
2019-01-23 15:09:10,255 INFO downstream2 [parallel-1] onNext(11)

如我们所见,DirectProcessor启用了必需的行为,因此很可能适合该行为。

注意

DirectProcessor不支持背压,因此如果背压很重要,可以在此处使用limitRate operator运算符。

另请参见

https://projectreactor.io/docs/core/release/reference/#_direct_processor