Flux
是 Spring WebFlux 中的核心类型之一,它的实现遵循 Reactive Streams 规范,基于 Publisher-Subscriber 模式,并结合了异步、非阻塞和背压机制。接下来我们从代码实现层面深入剖析 Flux
是如何实现的。
1. Flux 继承结构
在代码层面,Flux
继承了 Mono
,并且实现了 Publisher
接口。Mono
和 Flux
是响应式编程的基本构建块:
Mono<T>
:表示一个异步产生零或一个元素的数据流。Flux<T>
:表示一个异步产生零或多个元素的数据流。
public final class Flux<T> extends FluxSource<T> implements Publisher<T> {
// Flux 是 Publisher 的一种实现
}
FluxSource<T>
是Flux
的基础类,封装了流的具体实现。Flux
实现了Publisher<T>
,因此,它是响应式流的生产者。
2. Flux 和 Publisher 接口
Flux
实现了 Reactive Streams 规范中的 Publisher
接口,Publisher
接口定义了 subscribe
方法。通过这个方法,订阅者 (Subscriber
) 可以订阅数据流。订阅后,数据流才会被启动,Flux
开始将数据推送给订阅者。
public interface Publisher<T> {
void subscribe(Subscriber<? super T> s);
}
在 Flux
中,subscribe()
方法的实现是启动数据流的入口,下面是它的基本实现:
@Override
public void subscribe(Subscriber<? super T> s) {
// 创建 Subscription,并将其传递给 Subscriber
FluxSubscriber<T> fluxSubscriber = new FluxSubscriber<>(s);
s.onSubscribe(fluxSubscriber);
// 调用底层流的订阅方法来启动数据流
source.subscribe(fluxSubscriber);
}
这里,FluxSubscriber
是 Subscriber
的实现,负责将流的结果传递给订阅者,控制数据的消费过程。
3. Flux 数据流的处理
Flux
的实现利用了 惰性求值 和 链式操作 来处理数据流。每个操作符(如 map
、filter
)都生成一个新的 Flux
对象,这个新对象包含了对原始流的变换操作。
示例:map
操作符实现
当我们调用 map()
操作符时,实际上是对 Flux
进行了转换。map()
返回的是一个新的 Flux
对象,这个对象包含了将每个元素映射为新值的逻辑。
public final class Flux<T> {
public <R> Flux<R> map(Function<? super T, ? extends R> transformer) {
// 创建一个新的 Flux,封装转换操作
return new FluxMap<>(this, transformer);
}
}
FluxMap
是一个新的 Flux
实现类,它封装了 map
操作符的具体实现:
public final class FluxMap<T, R> extends Flux<R> {
private final Flux<? extends T> source;
private final Function<? super T, ? extends R> transformer;
public FluxMap(Flux<? extends T> source, Function<? super T, ? extends R> transformer) {
this.source = source;
this.transformer = transformer;
}
@Override
public void subscribe(Subscriber<? super R> s) {
// 在订阅时,应用转换逻辑
source.subscribe(new FluxMapSubscriber<>(s, transformer));
}
}
FluxMapSubscriber
是 Subscriber
的实现,它在 onNext()
方法中进行转换,并将结果传递给原始订阅者。
public class FluxMapSubscriber<T, R> implements Subscriber<T> {
private final Subscriber<? super R> actual;
private final Function<? super T, ? extends R> transformer;
public FluxMapSubscriber(Subscriber<? super R> actual, Function<? super T, ? extends R> transformer) {
this.actual = actual;
this.transformer = transformer;
}
@Override
public void onNext(T t) {
// 将元素应用转换函数
R transformed = transformer.apply(t);
actual.onNext(transformed);
}
@Override
public void onComplete() {
actual.onComplete();
}
@Override
public void onError(Throwable t) {
actual.onError(t);
}
}
4. 背压机制的实现
背压(Backpressure)是 Reactive Streams 规范的重要组成部分,它通过 Subscription
对象实现。Subscription
负责管理消费者与生产者之间的数据流量,确保当消费者处理不过来时,生产者不会继续发送数据。
关键代码:Subscription
相关
Flux
在 subscribe()
方法内部创建 FluxSubscriber
时,会向 Subscriber
注册 Subscription
:
public final class Flux<T> implements Publisher<T> {
@Override
public void subscribe(Subscriber<? super T> s) {
FluxSubscriber<T> fluxSubscriber = new FluxSubscriber<>(s);
s.onSubscribe(fluxSubscriber);
source.subscribe(fluxSubscriber);
}
}
FluxSubscriber
在收到数据时,会根据 request()
方法的调用来控制流量。背压的关键实现就在于 onSubscribe()
中的 request()
:
public class FluxSubscriber<T> implements Subscriber<T>, Subscription {
private final Subscriber<? super T> actual;
public FluxSubscriber(Subscriber<? super T> actual) {
this.actual = actual;
}
@Override
public void onSubscribe(Subscription subscription) {
// 接收到订阅时,通知订阅者请求数据
this.subscription = subscription;
actual.onSubscribe(this);
}
@Override
public void request(long n) {
// 请求n个元素,确保生产者不会无限制地发出元素
subscription.request(n);
}
@Override
public void cancel() {
subscription.cancel();
}
}
5. 线程调度与非阻塞
Flux
中的非阻塞和异步执行是通过 Scheduler
来实现的。Spring WebFlux 提供了多种调度策略,例如 subscribeOn()
和 publishOn()
,通过这些方法可以控制数据流的执行线程。
public final class Flux<T> {
public Flux<T> subscribeOn(Scheduler scheduler) {
return new FluxSubscribeOn<>(this, scheduler);
}
public Flux<T> publishOn(Scheduler scheduler) {
return new FluxPublishOn<>(this, scheduler);
}
}
subscribeOn(Scheduler scheduler)
用于指定数据流的订阅操作在哪个线程上执行。publishOn(Scheduler scheduler)
用于指定后续操作(如map
,filter
等)在哪个线程池中执行。
这两个方法分别通过 FluxSubscribeOn
和 FluxPublishOn
来实现。
6. 总结
Flux
的实现本质上是基于 Reactive Streams 规范的一个响应式数据流框架。它利用了 Publisher-Subscriber 模式 和 背压机制 来处理异步流,保证了系统在高并发场景下的高效性和可扩展性。
Flux
通过subscribe()
方法启动数据流。- 操作符(如
map
、filter
等)通过返回新的Flux
对象来进行数据流的转换。 - 背压机制通过
Subscription
实现,控制数据流速。 Scheduler
用于管理线程池,确保异步非阻塞执行。
这些设计确保了 Flux
能够高效、灵活地处理异步数据流,适应各种高并发和高负载的场景。