Project Reactor源码解析

背景

通过一个最简单的发布订阅流程探究底层机制

scss 复制代码
Flux.fromIterable(Arrays.asList(1, 2, 3, 4, 5))
    .filter(n -> n % 2 == 0)
    .map(n -> n * 10)
    .subscribe(System.out::println);

我们将从 subscribe 方法开始,详细分析订阅关系如何构建,层层嵌套形成完整的订阅链。


订阅关系构建的整体过程

订阅关系构建的核心是:通过 subscribe 方法将订阅者(Subscriber)与发布者(Publisher)关联起来,并在操作符链中插入中间订阅者,形成一个从下游到上游的订阅链。这个过程可以分为以下几个阶段:

  1. 触发订阅:调用 subscribe,传入最终订阅者。
  2. 操作符链的逆向构建:从最下游的操作符(map)开始,逐层向上游(filter、fromIterable)传播订阅请求,创建中间订阅者。
  3. 订阅关系的建立:每个操作符生成一个 Subscription 对象,绑定上下游,形成嵌套结构。
  4. 数据流准备:订阅链构建完成后,等待数据请求(request)触发数据流。

订阅关系构建是从下游到上游的,而数据流是从上游到下游的。这种反向构建是 Reactive Streams 规范的核心设计。

详细分析订阅关系构建

我们从 subscribe(System.out::println) 开始,逐步拆解订阅关系的构建过程。

触发订阅:subscribe 方法

调用 subscribe(System.out::println) 时,subscribe 方法的作用是将 System.out::println(一个 Consumer)包装为一个订阅者,并启动订阅流程。

源码分析:

Flux 类的 subscribe(Consumer) 方法定义如下:

java 复制代码
public final void subscribe(Consumer<? super T> consumer) {
    Objects.requireNonNull(consumer, "consumer");
    subscribe(consumer, null, null);
}
  • 检查 consumer 不为 null。
  • 调用重载方法 subscribe(Consumer, Consumer, Runnable),传入 consumer(System.out::println),错误和完成回调为 null。

接着看重载方法:

java 复制代码
public final void subscribe(Consumer<? super T> consumer,
                            Consumer<? super Throwable> errorConsumer,
                            Runnable completeConsumer) {
    subscribe(new LambdaSubscriber<>(consumer, errorConsumer, completeConsumer, null));
}
  • 创建一个 LambdaSubscriber 实例,将 System.out::println 包装为订阅者。
  • 调用 subscribe(Subscriber) 方法,传入 LambdaSubscriber。

最终调用的是:

ini 复制代码
public final void subscribe(Subscriber<? super T> s) {
    CorePublisher publisher = Operators.onLastAssembly(this);
    CoreSubscriber subscriber = Operators.toCoreSubscriber(s);
    publisher.subscribe(subscriber);
}
  • this 是当前的 Flux(经过 map 操作后的 FluxMap)。
  • Operators.onLastAssembly 处理调试信息(通常返回 this 本身)。
  • Operators.toCoreSubscriber 将 Subscriber 转换为 CoreSubscriber(内部优化接口)。
  • 调用 publisher.subscribe(subscriber),将订阅者绑定到发布者。

小结:

  • subscribe(System.out::println) 创建了一个 LambdaSubscriber,并调用 FluxMap.subscribe(LambdaSubscriber)。
  • 此时,LambdaSubscriber 是最终的订阅者,负责打印 [20, 40]。

操作符链的逆向构建

FluxMap 的订阅

FluxMap 是操作符链的最下游,接下来我们分析它如何向上游传播订阅请求,构建嵌套的订阅关系。 FluxMap 的 subscribe 方法定义如下:

typescript 复制代码
@Override
public void subscribe(CoreSubscriber<? super T> actual) {
    source.subscribe(new MapSubscriber<>(actual, mapper));
}
  • source 是上游的 Flux(这里是 FluxFilter,因为 map 的上游是 filter)。
  • actual 是下游的订阅者(这里是 LambdaSubscriber)。
  • 创建一个 MapSubscriber,传入 actual(LambdaSubscriber)和 mapper(n -> n * 10)。
  • 调用 source.subscribe,将 MapSubscriber 作为订阅者传递给上游。

MapSubscriber 的作用:

  • 接收上游数据,应用 mapper 转换后传递给下游。
  • 它的构造方法是:
kotlin 复制代码
MapSubscriber(CoreSubscriber<? super R> actual, Function<? super T, ? extends R> mapper) {
    this.actual = actual;
    this.mapper = mapper;
}
  • actual 是 LambdaSubscriber。
  • mapper 是 n -> n * 10。

小结:

  • FluxMap 创建了一个 MapSubscriber,作为中间订阅者,连接下游的 LambdaSubscriber 和上游的 FluxFilter。
  • 订阅请求传递到 FluxFilter.subscribe(MapSubscriber)。

FluxFilter 的订阅

FluxFilter 的 subscribe 方法如下:

typescript 复制代码
@Override
public void subscribe(CoreSubscriber<? super T> actual) {
    source.subscribe(new FluxFilter.FilterSubscriber<>(actual, predicate));
}
  • source 是上游的 Flux(这里是 FluxFromIterable)。
  • actual 是下游的订阅者(这里是 MapSubscriber)。
  • 创建一个 FilterSubscriber,传入 actual(MapSubscriber)和 predicate(n -> n % 2 == 0)。
  • 调用 source.subscribe,将 FilterSubscriber 传递给上游。

FilterSubscriber 的作用:

  • 接收上游数据,应用 predicate 过滤后传递给下游。
  • 构造方法是:
kotlin 复制代码
FilterSubscriber(CoreSubscriber<? super T> actual, Predicate<? super T> predicate) {
    this.actual = actual;
    this.predicate = predicate;
}
  • actual 是 MapSubscriber。
  • predicate 是 n -> n % 2 == 0。

小结:

  • FluxFilter 创建了一个 FilterSubscriber,连接下游的 MapSubscriber 和上游的 FluxFromIterable。
  • 订阅请求传递到 FluxFromIterable.subscribe(FilterSubscriber)。

FluxFromIterable 的订阅

FluxFromIterable 是数据流的起点,它的 subscribe 方法如下:

kotlin 复制代码
@Override
public void subscribe(CoreSubscriber<? super T> actual) {
    Iterator<?> iterator;
    try {
        iterator = Objects.requireNonNull(iterable.iterator(), "The iterator returned is null");
    } catch (Throwable e) {
        Operators.error(actual, Operators.onOperatorError(e, actual.currentContext()));
        return;
    }
    actual.onSubscribe(new IterableSubscription<>(actual, iterator));
}
  • actual 是下游的订阅者(这里是 FilterSubscriber)。
  • 从 iterable(Arrays.asList(1, 2, 3, 4, 5))获取迭代器。
  • 创建一个 IterableSubscription,传入 actual(FilterSubscriber)和迭代器。
  • 调用 actual.onSubscribe,将 IterableSubscription 传递给 FilterSubscriber。

IterableSubscription 的作用:

  • 作为 Subscription 的实现,管理数据请求和发送。
  • 从迭代器生成数据,响应 request(n) 调用。

小结:

  • FluxFromIterable 创建了 IterableSubscription,而订阅关系是连接下游订阅者 FilterSubscriber 和数据源(List)的桥梁
  • 至此,订阅链构建完成。

Subscription 订阅关系的构建与触发

从 FluxFromIterable 调用 FilterSubscriber.onSubscribe 开始,继续分析后续链路。

  1. onSubscribe 的触发与传递

在订阅关系构建的最后一步,FluxFromIterable 的 subscribe 方法调用了:

typescript 复制代码
@Override
public void subscribe(CoreSubscriber<? super T> actual) {
    Iterator<?> iterator = iterable.iterator();
    actual.onSubscribe(new IterableSubscription<>(actual, iterator));
}
  • actual 是 FilterSubscriber。
  • 创建 IterableSubscription 并调用 FilterSubscriber.onSubscribe。

1.1 FilterSubscriber.onSubscribe

FilterSubscriber 继承自 BaseSubscriber 或类似基类,其 onSubscribe 方法通常由 Operators 工具类实现。实际行为类似于:

kotlin 复制代码
@Override
public void onSubscribe(Subscription s) {
    if (Operators.validateSubscription(this.s, s)) {
        this.s = s;
        actual.onSubscribe(this);
    }
}
  • s 是 IterableSubscription。
  • Operators.validateSubscription 检查订阅是否有效(防止重复订阅)。
  • this.s 保存上游的 Subscription,用于后续请求数据。
  • actual 是下游的 MapSubscriber,调用 actual.onSubscribe(this),将 FilterSubscriber 自身作为 Subscription 传递给下游。

关键点:

  • FilterSubscriber 既是 Subscriber(接收上游信号),也是 Subscription(向下游提供控制接口)。
  • 它将 IterableSubscription 包装后传递给下游,形成嵌套的 Subscription 链。

1.2 MapSubscriber.onSubscribe

MapSubscriber 的 onSubscribe 逻辑类似:

kotlin 复制代码
@Override
public void onSubscribe(Subscription s) {
    if (Operators.validateSubscription(this.s, s)) {
        this.s = s;
        actual.onSubscribe(this);
    }
}
  • s 是 FilterSubscriber。
  • 保存上游的 Subscription(FilterSubscriber)。
  • actual 是 LambdaSubscriber,调用 actual.onSubscribe(this),将 MapSubscriber 传递给下游。

1.3 LambdaSubscriber.onSubscribe

LambdaSubscriber 是最终订阅者,其 onSubscribe 定义如下:

typescript 复制代码
@Override
public void onSubscribe(Subscription s) {
    if (Operators.setOnce(S, this, s)) {
        if (requestConsumer != null) {
            requestConsumer.accept(s);
        } else {
            s.request(Long.MAX_VALUE);
        }
    }
}
  • s 是 MapSubscriber。
  • Operators.setOnce 确保订阅只设置一次。
  • requestConsumer 默认为空,因此调用 s.request(Long.MAX_VALUE),请求无限数据。

小结:

  • onSubscribe 从上游到下游逐层传递:

    • IterableSubscription → FilterSubscriber
    • FilterSubscriber → MapSubscriber
    • MapSubscriber → LambdaSubscriber
  • 最终,LambdaSubscriber 触发 request(Long.MAX_VALUE),启动数据流。


  1. 数据请求的触发

LambdaSubscriber 调用 MapSubscriber.request(Long.MAX_VALUE),请求数据。接下来,请求信号从下游到上游传递。

2.1 MapSubscriber.request

MapSubscriber 继承自 BaseSubscriber 或类似类,其 request 方法如下:

java 复制代码
@Override
public void request(long n) {
    s.request(n);
}
  • s 是上游的 FilterSubscriber。
  • 将请求直接传递给 FilterSubscriber。

2.2 FilterSubscriber.request

FilterSubscriber 的 request 方法类似:

java 复制代码
@Override
public void request(long n) {
    s.request(n);
}
  • s 是上游的 IterableSubscription。
  • 将请求传递给 IterableSubscription。

2.3 IterableSubscription.request

IterableSubscription 的 request 方法是数据流的实际起点:

scss 复制代码
@Override
public void request(long n) {
    if (Operators.validate(n)) {
        if (Operators.addCap(REQUESTED, this, n) == 0) {
            if (n == Long.MAX_VALUE) {
                fastPath();
            } else {
                slowPath(n);
            }
        }
    }
}
  • Operators.validate(n) 检查请求是否有效(n > 0)。
  • Operators.addCap 累加请求数,避免溢出。
  • 因为 n == Long.MAX_VALUE,执行 fastPath():
ini 复制代码
void fastPath() {
    final CoreSubscriber<? super T> a = actual;
    final Iterator<?> it = iterator;
    for (;;) {
        if (cancelled) return;
        boolean hasNext;
        try {
            hasNext = it.hasNext();
        } catch (Throwable ex) {
            Operators.error(a, Operators.onOperatorError(this, ex, a.currentContext()));
            return;
        }
        if (cancelled) return;
        if (!hasNext) {
            if (!cancelled) a.onComplete();
            return;
        }
        T t;
        try {
            t = Objects.requireNonNull(it.next(), "Iterator returned a null value");
        } catch (Throwable ex) {
            Operators.error(a, Operators.onOperatorError(this, ex, a.currentContext()));
            return;
        }
        if (cancelled) return;
        a.onNext(t);
    }
}
  • actual 是 FilterSubscriber。
  • iterator 是 List 的迭代器。
  • 循环遍历 [1, 2, 3, 4, 5],逐个调用 FilterSubscriber.onNext。
  • 数据发送完后,调用 FilterSubscriber.onComplete。

  1. 数据流的处理

数据从上游到下游流动,经过每个订阅者的处理。

3.1 FilterSubscriber.onNext

FilterSubscriber 的 onNext 方法:

typescript 复制代码
@Override
public void onNext(T t) {
    if (isCancelled()) return;
    if (predicate.test(t)) {
        actual.onNext(t);
    }
}
  • t 是从 IterableSubscription 收到的数据(如 1、2 等)。

  • predicate 是 n -> n % 2 == 0。

  • 如果 t 通过过滤(是偶数),调用 actual.onNext(t)(actual 是 MapSubscriber)。

  • 处理过程:

    • 1:不通过,丢弃。
    • 2:通过,调用 MapSubscriber.onNext(2)。
    • 3:丢弃。
    • 4:通过,调用 MapSubscriber.onNext(4)。
    • 5:丢弃。

3.2 MapSubscriber.onNext

MapSubscriber 的 onNext 方法:

kotlin 复制代码
@Override
public void onNext(T t) {
    if (isCancelled()) return;
    R v;
    try {
        v = Objects.requireNonNull(mapper.apply(t), "The mapper returned a null value");
    } catch (Throwable ex) {
        cancel();
        actual.onError(Operators.onOperatorError(this, ex, t, actual.currentContext()));
        return;
    }
    actual.onNext(v);
}
  • t 是从 FilterSubscriber 收到的数据(如 2、4)。

  • mapper 是 n -> n * 10。

  • 转换后调用 actual.onNext(v)(actual 是 LambdaSubscriber)。

  • 处理过程:

    • 2:转换为 20,调用 LambdaSubscriber.onNext(20)。
    • 4:转换为 40,调用 LambdaSubscriber.onNext(40)。

3.3 LambdaSubscriber.onNext

LambdaSubscriber 的 onNext 方法:

typescript 复制代码
@Override
public void onNext(T t) {
    if (consumer != null) {
        try {
            consumer.accept(t);
        } catch (Throwable e) {
            Operators.onErrorDropped(e, currentContext());
        }
    }
}
  • t 是从 MapSubscriber 收到的数据(如 20、40)。

  • consumer 是 System.out::println。

  • 调用 consumer.accept(t),打印:

    • 20
    • 40

  1. 完成信号的传递

数据处理完成后,IterableSubscription 调用 FilterSubscriber.onComplete。

4.1 FilterSubscriber.onComplete

typescript 复制代码
@Override
public void onComplete() {
    if (!isCancelled()) {
        actual.onComplete();
    }
}
  • 调用 MapSubscriber.onComplete。

4.2 MapSubscriber.onComplete

typescript 复制代码
@Override
public void onComplete() {
    if (!isCancelled()) {
        actual.onComplete();
    }
}
  • 调用 LambdaSubscriber.onComplete。

4.3 LambdaSubscriber.onComplete

typescript 复制代码
@Override
public void onComplete() {
    if (completeConsumer != null) {
        try {
            completeConsumer.run();
        } catch (Throwable e) {
            Operators.onErrorDropped(e, currentContext());
        }
    }
}
  • completeConsumer 是 null,因此无额外操作。
  • 数据流结束。

  1. 完整链路总结

从 onSubscribe 触发后:

  1. Subscription 传递:

    • IterableSubscription → FilterSubscriber → MapSubscriber → LambdaSubscriber。
  2. request 触发:

    • LambdaSubscriber.request(Long.MAX_VALUE) 逐层传递至 IterableSubscription。
  3. 数据流处理:

    • IterableSubscription 发送 [1, 2, 3, 4, 5]。
    • FilterSubscriber 过滤出 [2, 4]。
    • MapSubscriber 转换为 [20, 40]。
    • LambdaSubscriber 打印 20, 40。
  4. 完成信号:

    • IterableSubscription.onComplete 逐层传递至 LambdaSubscriber。

  1. 为什么这样设计后续链路
  • 背压支持:request 从下游到上游传递,控制数据流速率。
  • 异步性:每个订阅者可以在不同线程处理(如通过 publishOn),嵌套结构支持线程切换。
  • 错误隔离:onError 可在任意层级触发并处理,防止整个链崩溃。
相关推荐
Philosophy21 天前
响应式编程之Project Reactor
响应式编程·java 并发
糖心何包蛋爱编程24 天前
(六)Reactive-Stream 响应式流
java·开发语言·响应式编程·干货分享
糖心何包蛋爱编程24 天前
(二)Reactor核心-前置知识1
java·响应式编程·lambda表达式·干货分享
糖心何包蛋爱编程25 天前
(四)Reactor核心-前置知识3
java·开发语言·经验分享·响应式编程·streamapi
刘同学有点忙1 个月前
浏览器内置响应式编程?用 TC39 Signals 提案实现 TodoList
前端·响应式编程
answerball1 个月前
🔥 Vue3响应式源码深度解剖:从Proxy魔法到依赖收集,手把手教你造轮子!🚀
前端·响应式设计·响应式编程
Philosophy1 个月前
响应式编程之Reactive Streams介绍
响应式编程
小小工匠2 个月前
响应式编程_03响应式编程在Netflix Hystrix 、Spring Cloud Gateway、Spring WebFlux中的应用
hystrix·gateway·响应式编程·webflux
Diligent_lvan3 个月前
步入响应式编程篇(二)之Reactor API
响应式编程·reactor api