热发布者与冷发布者
到目前为止,我们一直认为所有 Flux(以及 Mono)都是相同的:它们都表示一个异步的数据序列,并且在您订阅之前不会发生任何事情。
不过实际上,发布者大致分为两大类:热发布者和冷发布者。
前面的描述适用于冷发布者这一类。它们会为每次订阅重新生成数据。如果没有创建订阅,数据就永远不会被生成。
以 HTTP 请求为例:每个新的订阅者都会触发一次 HTTP 调用,但如果没有人关心结果,就不会发起任何调用。
而热发布者则不同,它不依赖于订阅者的数量。它可能一开始就开始发布数据,并且无论何时有新的 Subscriber 加入都会持续发布(在这种情况下,该订阅者只能看到它订阅之后新发出的元素)。对于热发布者来说,在您订阅之前确实已经发生了一些事情。
Reactor 中少数热操作符之一的例子是 just:它在组装时就直接捕获值,并在之后重放给任何订阅它的人。沿用 HTTP 调用的类比,如果捕获的数据是一次 HTTP 调用的结果,那么在实例化 just 时只会发起一次网络调用。
要把 just 转换成冷发布者,您可以使用 defer。在我们的示例中,它会把 HTTP 请求延迟到订阅时才发起(并且每次新的订阅都会导致一次单独的网络调用)。
相反,share() 和 replay(…) 可用于把冷发布者变成热发布者(至少在发生了第一次订阅之后)。这两个操作符在 Sinks 类中也都有对应的 Sinks.Many 等价物,它们允许以编程方式向序列供给数据。
请看两个示例:一个演示冷 Flux,另一个利用 Sinks 模拟热 Flux。以下代码展示了第一个示例:
Flux<String> source = Flux.fromIterable(Arrays.asList("blue", "green", "orange", "purple"))
.map(String::toUpperCase);
source.subscribe(d -> System.out.println("Subscriber 1: "+d));
source.subscribe(d -> System.out.println("Subscriber 2: "+d));
第一个示例产生如下输出:
Subscriber 1: BLUE
Subscriber 1: GREEN
Subscriber 1: ORANGE
Subscriber 1: PURPLE
Subscriber 2: BLUE
Subscriber 2: GREEN
Subscriber 2: ORANGE
Subscriber 2: PURPLE
下图展示了重放行为:

两个订阅者都收到了全部四种颜色,因为每次订阅都会触发 Flux 上各操作符所定义的处理流程运行。
把第一个示例与第二个示例对比,第二个示例如下列代码所示:
Sinks.Many<String> hotSource = Sinks.unsafe().many().multicast().directBestEffort();
Flux<String> hotFlux = hotSource.asFlux().map(String::toUpperCase);
hotFlux.subscribe(d -> System.out.println("Subscriber 1 to Hot Source: "+d));
hotSource.emitNext("blue", FAIL_FAST); 1
hotSource.tryEmitNext("green").orThrow(); 2
hotFlux.subscribe(d -> System.out.println("Subscriber 2 to Hot Source: "+d));
hotSource.emitNext("orange", FAIL_FAST);
hotSource.emitNext("purple", FAIL_FAST);
hotSource.emitComplete(FAIL_FAST);
有关 sinks 的更多详细信息,请参阅 Sinks
附带说明:这里的
orThrow()是emitNext+Sinks.EmitFailureHandler.FAIL_FAST的一种替代写法,适合用于测试,因为在这里抛出异常是可以接受的(比在响应式应用中更可接受)。
第二个示例产生如下输出:
Subscriber 1 to Hot Source: BLUE
Subscriber 1 to Hot Source: GREEN
Subscriber 1 to Hot Source: ORANGE
Subscriber 2 to Hot Source: ORANGE
Subscriber 1 to Hot Source: PURPLE
Subscriber 2 to Hot Source: PURPLE
下图展示了订阅是如何被广播的:

Subscriber 1 收到了全部四种颜色。Subscriber 2 是在前两种颜色产生之后才创建的,因此只收到了最后两种颜色。这一差异导致输出中的 ORANGE 和 PURPLE 出现了两次。无论订阅在何时挂载,这个 Flux 上各操作符所描述的处理流程都会照常运行。