webflux之reactor

webflux是spring框架中用来和springmvc进行互补的,一套全新的非阻塞响应式流处理框架。其中响应式流处理的依赖包,webflux选择的是Reactor。

在这里插入图片描述

下面来简单介绍一下Reactor

核心接口Reactive Streams

reactor实现的是org.reactivestreams的一套标准接口reactive-streams
Reactive Streams的目的是为具有非阻塞背压的异步流处理提供标准。
由以下组件组成

Publisher
package org.reactivestreams;

/**
 发布者是可能无限数量的有序元素的提供者,根据从其订阅者收到的需求发布它们。
 发布者可以在不同的时间点动态地为多个订阅者订阅订阅(订阅者)。
 */
public interface Publisher<T> {

    /**
     请求Publisher启动流数据。
	 这是一个“工厂方法”,可以多次调用,每次启动一个新的订阅。
	 每个订阅仅适用于一个订阅者。
	 订阅者只应订阅一个发布者一次。
	 如果发布者拒绝订阅尝试或以其他方式失败,它将通过Subscriber.onError发出错误信号。
     */
    public void subscribe(Subscriber<? super T> s);
}
Subscriber
package org.reactivestreams;

/**
将订阅者实例传递给Publisher.subscribe(订阅者)后,将接收对onSubscribe(订阅)的调用。
在调用Subscription.request(long)之前不会收到进一步的通知。

发出信号后需求:
onNext(Object)的一次或多次调用,最多为Subscription.request(long)定义的最大数量
单次调用onError(Throwable)或onComplete(),它指示终端状态,之后不再发送任何事件。

只要Subscriber实例能够处理更多内容,就可以通过Subscription.request(long)发出需求信号。
 */
public interface Subscriber<T> {
    /**
	调用Publisher.subscribe(订阅者)后调用。
	在调用Subscription.request(long)之前,任何数据都不会开始流动。
	只要需要更多数据,此Subscriber实例就有责任调用Subscription.request(long)。
	发布者仅在响应Subscription.request(long)时发送通知。	
     */
    public void onSubscribe(Subscription s);

    /**
     * 发布者为响应对Subscription.request(long)的请求而发送的数据通知。
     * @param t the element signaled
     */
    public void onNext(T t);

    /**
     终端状态失败。
	 即使再次调用Subscription.request(long),也不会发送更多事件。
     */
    public void onError(Throwable t);

    /**
	成功的终端状态。
	即使再次调用Subscription.request(long),也不会发送更多事件。
     */
    public void onComplete();
}

Subscription
package org.reactivestreams;

/**
 订阅表示订阅发布者的订阅者的一对一生命周期。
 它只能由一个订阅者使用一次。
 它用于表示对数据的需求和取消需求(并允许资源清理)。
 *
 */
public interface Subscription {
    /**
	 在通过此方法发出需求信号之前,发布者不会发送任何事件。
	 然而,无论何时需要,它都可以被调用 - 但是未完成的累积需求绝不能超过Long.MAX_VALUE。 Long.MAX_VALUE的未完成累积需求可能会被发布者视为“有效无限制”。
	 发布者可以发送任何请求,因此只需要发出可以安全处理的信号需求。
	 如果流结束但发布者可以发送少于请求的发送者,但必须发出Subscriber.onError(Throwable)或Subscriber.onComplete()。
	
	 PARAMS:
	 n - 向上游发布者请求的严格正数元素
     */
    public void request(long n);

    /**
     请求发布者停止发送数据并清理资源。
	 在呼叫取消后,仍可以发送数据以满足先前发出的信号要求。
     */
    public void cancel();
}
Processor
package org.reactivestreams;

/**
	处理器代表一个处理阶段 - 既是订阅者又是发布者,并遵守两者的合同。
	类型参数:
	<T> - 发信号通知订阅者的元素类型
	<R> - 发布者发出信号的元素类型
 */
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
demo讲解

Reactor引入了可实现Publisher的可组合响应式类型,同时也提供了丰富的运算符:Flux和Mono。Flux对象表示0…N项的响应式序列,而Mono对象表示单值或空(0…1)结果。

demo1

import reactor.core.publisher.Flux;

/**
 * Created by aaron on 2018/9/27.
 */
public class FluxSample {

    public void demo1(){
        //构建一个Flux,它从头开始只发出一系列计数递增整数。
        //start - 要发出的第一个整数 ; count - 要发出的递增值的总数,包括第一个值
        Flux<Integer> ints = Flux.range(2, 4);    //分解步骤1
        //将消费者订阅到此Flux,它将分别消耗序列中的所有元素,处理错误并对完成做出反应。
        ints.subscribe(                           //分解步骤2
                //实现一个消费者(注意无返回结果)
                i -> System.out.println(i),
                //实现一个可以调用的错误信号的消费者
                error -> System.err.println("Error " + error),
                //实现一个在发送一个完成信号后的回调
                () -> System.out.println("Done"));
    }

    public static void main(String[] args) {

        FluxSample fluxSample = new FluxSample();
        fluxSample.demo1();


    }
}

分解步骤1
通过Flux.range(2, 4)创建了一个Flux,发送一系列计数递增整数
在这里插入图片描述

	public static Flux<Integer> range(int start, int count) {
		if (count == 1) {
			return just(start);
		}
		if (count == 0) {
			return empty();
		}
		return onAssembly(new FluxRange(start, count));
	}
	
	protected static <T> Flux<T> onAssembly(Flux<T> source) {
		//这里的hook为null,直接返回source
		Function<Publisher, Publisher> hook = Hooks.onEachOperatorHook;
		if(hook == null) {
			return source;
		}
		return (Flux<T>)hook.apply(source);
	}

//最终创建的是一个FluxRange对象,对start和end属性进行了赋值
final class FluxRange extends Flux<Integer> implements Fuseable, Scannable {

	final long start;

	final long end;

	FluxRange(int start, int count) {
		if (count < 0) {
			throw new IllegalArgumentException("count >= required but it was " + count);
		}
		//end被赋值为start + count
		long e = (long) start + count;
		if (e - 1 > Integer.MAX_VALUE) {
			throw new IllegalArgumentException("start + count must be less than Integer.MAX_VALUE + 1");
		}

		this.start = start;
		this.end = e;
	}
	...
}

分解步骤2
ints.subscribe这个方法触发了一个消费者对发布(Flux)的订阅,这里订阅将请求无限制的需求(Long.MAX_VALUE)
在这里插入图片描述

	/*
	consumer - 要调用每个值的使用者
	errorConsumer - 调用错误信号的消费者
	completeConsumer - 消费者调用完整信号
	*/
	public final Disposable subscribe(
			@Nullable Consumer<? super T> consumer,
			@Nullable Consumer<? super Throwable> errorConsumer,
			@Nullable Runnable completeConsumer) {
		return subscribe(consumer, errorConsumer, completeConsumer, null);
	}


	public final Disposable subscribe(
			@Nullable Consumer<? super T> consumer,
			@Nullable Consumer<? super Throwable> errorConsumer,
			@Nullable Runnable completeConsumer,
			@Nullable Consumer<? super Subscription> subscriptionConsumer) {
			//这里最终是创建了一个LambdaSubscriber(一个Subscriber的实现类)
		return subscribeWith(new LambdaSubscriber<>(consumer, errorConsumer,
				completeConsumer,
				subscriptionConsumer));
	}

//一个无边界Java Lambda的Subscriber适配器
final class LambdaSubscriber<T>
		implements InnerConsumer<T>, Disposable {

	final Consumer<? super T>            consumer;
	final Consumer<? super Throwable>    errorConsumer;
	final Runnable                       completeConsumer;
	final Consumer<? super Subscription> subscriptionConsumer;

	volatile Subscription subscription;
	...
	/**
	创建订阅者,对onNext,onError和onComplete做出反应。 订阅者将自动请求订阅Long.MAX_VALUE。
	 */
	LambdaSubscriber(
			@Nullable Consumer<? super T> consumer,
			@Nullable Consumer<? super Throwable> errorConsumer,
			@Nullable Runnable completeConsumer,
			@Nullable Consumer<? super Subscription> subscriptionConsumer) {
		this.consumer = consumer;
		this.errorConsumer = errorConsumer;
		this.completeConsumer = completeConsumer;
		this.subscriptionConsumer = subscriptionConsumer;
	}
	...
	@Override
	public final void onNext(T x) {
		try {
			if (consumer != null) {
				//这里调用的就是 i -> System.out.println(i),参数x对应i
				consumer.accept(x);
			}
		}
		catch (Throwable t) {
			Exceptions.throwIfFatal(t);
			this.subscription.cancel();
			onError(t);
		}
	}
	...
	@Override
	public final void onComplete() {
		Subscription s = S.getAndSet(this, Operators.cancelledSubscription());
		if (s == Operators.cancelledSubscription()) {
			return;
		}
		if (completeConsumer != null) {
			try {
				//这里调用的complete以后的回调
				//() -> System.out.println("Done")); 将会输出"Done"
				completeConsumer.run();
			}
			catch (Throwable t) {
				Exceptions.throwIfFatal(t);
				onError(t);
			}
		}
	}
	...
}

上面的代码介绍到subscribeWith(new LambdaSubscriber<>(…))这行。下面来继续追踪subscribeWith(…)这个方法

序号方法
1Flux6870 return subscribeWith(new LambdaSubscriber<>(…)
2Flux7044 subscribe(subscriber);
3Flux6877 onLastAssembly(this).subscribe(Operators.toCoreSubscriber(actual));
4FluxRange52 public void subscribe(CoreSubscriber<? super Integer> actual) {
5LambdaSubscriber75 public final void onSubscribe(Subscription s) {
6FluxRange.RangeSubscription103 public void request(long n) {
7FluxRange.RangeSubscription120 void fastPath() {

到这里就进入了真正执行onNext或者onComplete相关的方法了

void fastPath() {
			final long e = end;
			//这里的a就是LambdaSubscriber
			final Subscriber<? super Integer> a = actual;
		
			for (long i = index; i != e; i++) {
				if (cancelled) {
					return;
				}
				//这里循环执行onNext,对应LambdaSubscriber中的onNext
				a.onNext((int) i);
			}

			if (cancelled) {
				return;
			}
			//这里循环执行onComplete,对应LambdaSubscriber中的onComplete
			a.onComplete();
		}

这里循环结束就输出“Done”,走完了整个demo

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值