webflux之reactor-Publisher

在进行第二个demo之前。先来讲解一下reactive-streams官网中有关Publisher的一些规则。这里将基于第一篇reactor博客中的demo进行讲解。demo1。

public interface Publisher<T> {
    public void subscribe(Subscriber<? super T> s);
}
Publisher规则
  1. 发布者向订阅者发出的onNext总数必须小于或等于该订阅者订阅所请求的元素总数。
    此规则的目的是明确发布者不能发出比订阅者请求的更多元素的信号。

    代码1

    public void demo2(){
    	//这里发布数量为4个
        Flux<Integer> ints = Flux.range(1, 4);
        ints.subscribe(i -> System.out.println(i),
                error -> System.err.println("Error " + error),
                () -> System.out.println("Done"),
                //注意这里定义了request数量为10个,满足规则1
                sub -> sub.request(10));
    }
    
  2. 发布者可以通过调用onComplete或onError来发出更少的onNext信号,并终止订阅。
    此规则的目的是明确说明发布者无法保证它能够生成所请求的元素数量;它可能根本无法生产它们;它可能处于失败状态;它可能是空的或已经完成。

    代码2 参考FluxRange类

    void fastPath() {
    	final long e = end;
    	final Subscriber<? super Integer> a = actual;
    	for (long i = index; i != e; i++) {
    		if (cancelled) {
    			return;
    		}
    		a.onNext((int) i);
    	}
    	if (cancelled) {
    		return;
    	}
    	//for循环执行完成,并且没有触发cancelled,就会调用onComplete()
    	a.onComplete();
    }
    
  3. onSubscribe,onNext,onError和onComplete用信号发送给订阅者必须以线程安全的方式发出信号 - 如果由多个线程执行 - 使用外部同步。
    此规则的目的是清楚地表明,如果发布者打算从多个/不同的线程发送信号,则必须采用外部同步。

  4. 如果发布者失败,它必须发出onError信号
    此规则的目的是明确说明如果发布者检测到无法继续,则发布者负责通知其订阅者 - 必须为订阅者提供清理资源或以其他方式处理发布者失败的机会。(本例中没有出现这条规则的情况)

  5. 如果发布者成功终止(有限流),它必须发出onComplete信号。
    此规则的目的是明确说明发布者负责通知其订阅者它已达到终端状态 - 订阅者可以对此信息采取行动;清理资源等。见代码2.

  6. 如果发布者在订阅者上发出onError或onComplete信号,则该订阅者的订阅必须被视为已取消。
    此规则的目的是确保订阅被视为相同,无论它是否被取消,发布者发出onError或onComplete信号。
    代码3 LambdaSubscriber类

    @Override
    public final void onComplete() {
    	Subscription s = S.getAndSet(this, Operators.cancelledSubscription());
    	if (s == Operators.cancelledSubscription()) {
    		return;
    	}
    	if (completeConsumer != null) {
    		try {
    			completeConsumer.run();
    		}
    		catch (Throwable t) {
    			Exceptions.throwIfFatal(t);
    			onError(t);
    		}
    	}
    }
    
    @Override
    public final void onError(Throwable t) {
    	Subscription s = S.getAndSet(this, Operators.cancelledSubscription());
    	if (s == Operators.cancelledSubscription()) {
    		Operators.onErrorDropped(t, Context.empty());
    		return;
    	}
    	if (errorConsumer != null) {
    		errorConsumer.accept(t);
    	}
    	else {
    		throw Exceptions.errorCallbackNotImplemented(t);
    	}
    }
    

    从代码中可以看到无论是onError或onComplete,在调用之后都将Subscription赋值为Operators.cancelledSubscription(),其值为一个常量对象。见以下代码。

    代码4

    final static class CancelledSubscription implements Subscription, Scannable {
    	static final CancelledSubscription INSTANCE = new CancelledSubscription();
    
    	@Override
    	@Nullable
    	public Object scanUnsafe(Attr key) {
    		if (key == Attr.CANCELLED) {
    			return true;
    		}
    		return null;
    	}
    	@Override
    	public void cancel() {
    		// deliberately no op
    	}
    	@Override
    	public void request(long n) {
    		// deliberately no op
    	}
    }
    
  7. 一旦发出终端状态信号(onError,onComplete),就要求不再发送其他信号。
    此规则的目的是确保onError和onComplete是发布服务器和订阅服务器对之间交互的最终状态。

  8. 如果订阅被取消,其订户必须最终停止​​收到信号。
    此规则的目的是确保发布者在调用Subscription.cancel()时尊重订阅者取消订阅的请求。 最终的原因是因为信号由于异步而具有传播延迟。
    从代码2中可以看到对cancelled变量的逻辑判断既是对这条规则的满足。

  9. Publisher.subscribe必须在提供的订阅者的任何其他信号之前调用onSubscribe,并且必须正常返回,除非提供的订阅者为null,在这种情况下它必须向调用者抛出java.lang.NullPointerException,以适用于所有其他情况信号失败(或拒绝订阅者)的唯一合法方式是调用onError(在调用onSubscribe之后)。
    此规则的目的是确保始终在任何其他信号之前发信号通知onSubscribe,以便在接收到信号时订阅服务器可以执行初始化逻辑。 另外onSubscribe只能被调用一次。 如果提供的Subscriber为null,则除此之外没有其他地方向调用者发出信号,这意味着必须抛出java.lang.NullPointerException。
    demo1中的调用流程可以说明这条规则

  10. 可以根据需要多次调用Publisher.subscribe,但每次都必须使用不同的订阅者
    此规则的目的是让订阅者知道不能假定通用发布者和通用订阅者支持多次附加。 此外,它还要求无论调用多少次都必须维护订阅的语义。

  11. 发布者可以支持多个订阅者,并决定每个订阅是单播还是多播。
    此规则的目的是为Publisher实现提供灵活性,以确定它们将支持多少(如果有)订阅者,以及如何分发元素。

你可能感兴趣的:(java架构)