Erlo

JVM平台上的响应式流(Reactive Streams)规范

时间:2019-02-12 02:02   阅读:152次   来源:博客园页面报错

点赞

 

 

//
Reactive Streams
//



响应式流是一个倡议,用来为具有非阻塞后压的异步流处理提供一个标准。大家努力的目标集中在运行时环境(JVM和JavaScript)和网络协议上。

注:响应式流其实就是一个规范,本文讲解的正是这个规范,且这个规范已经被引入到JDK9里了。



后压:就是下游出现了问题,得不到解决时,这个问题就会逆流而上,继而影响上游。

如果一个路口红绿灯坏了造成堵车,如果不管的话,用不了太长时间,车就会堵到上一个路口,如果再不管的话,整条路都会被赌满。



//
JDK9里的java.util.concurrent.Flow
//



本规范里的这些接口在JDK9的java.util.concurrent.Flow里都已经可用,它们在语义上与响应式流的各接口基本上一比一相等。

这意味着将有一个迁移周期,直至第三方库都采用JDK里的新类型,这个周期自然希望短一些。

这取决于第三方库的完整语义相等,和Reactive Streams和JDK的Flow之间的适配器库和一个与JDK的Flow类型可直接兼容的TCK。



因为这个标准在JDK9才引入,在此之前一些第三方库都已经存在,所以需要一个过渡阶段,让第三方库慢慢采用JDK的标准。


TCK是一个工具,下文有介绍。



//
Goals, Design and Scope
//



处理流数据,尤其是在线数据,它们的量是无法预知的,在一个异步系统中要求格外小心。

最重要的问题是资源的消耗需要被小心地控制,以便一个快速的数据源不会淹没流的目的地(下游)。

需要异步的目的是为了并行地使用计算资源,如协调网络上多个主机,或一个机器的多个CPU核。

响应式流的主要目标是控制横穿一个异步边界的流数据的交换。

考虑到向另一个线程或线程池传递元素,同时确保接收端不被强迫缓冲任意数量的数据。

换句话说,后压是这个模型的一个必须部分,目的是允许队列在被界定的线程之间进行调节(斡旋)。

如果后压信号是同步的,异步处理的好处将被否定,因此对一个响应式流实现的所有方面的完全非阻塞和异步行为的授权需要小心一些。

这个规范的意图就是允许创建许多种一致的实现,它们凭借遵守规则将能够平滑地互操作,在一个流应用的整个处理图中保留前文提到的好处和特征。

需要注意的是流操作的精确特性(转化,分割,合并等)并没有被这个规范包括。响应式流只关心在不同的API组件间调节流数据。在他们的开发中,已经非常细心地确保所有组合流的基本方式都能够被表达。

总之,响应式流是JVM上面向流的库的一个标准和规范:

处理一个潜在的无限数目元素,
依次地,
异步地在组件间传递元素,
带有强制的非阻塞后压。


响应式流规范由以下部分组成:

1、API规定了需要实现的响应式流类型,并且在不同的实现间完成互操作性。

2、技术兼容性工具(TCK)是一个标准的测试套件,用于各种实现的一致性测试。

各种实现可以自由地实现规范中没有提到的额外特性,只要它们遵从API要求和在TCK中通过测试。



//
API Components
//



API由以下组件组成,响应式流的实现必须提供它们:

1、Publisher,发布者(生产者)
2、Subscriber,订阅者(消费者)
3、Subscription,订阅
4、Processor,处理者

它们其实是4个接口,先睹为快:


public interface Publisher<T{
    public void subscribe(Subscriber<? super T> s);
}

public interface Subscriber<T{
    public void onSubscribe(Subscription s);
    public void onNext(T t);
    public void onError(Throwable t);
    public void onComplete();
}

public interface Subscription {
    public void request(long n);
    public void cancel();
}

public interface Processor<TRextends Subscriber<T>, Publisher<R{

}


一个发布者是一个潜在的无限数量的序列元素的一个提供者,按照收到的来自于它的订阅者的需要来发布这些元素。

作为对发布者的subscribe(Subscriber)方法调用的响应,对于订阅者上的方法的可能调用顺序按下面的协议给出:


onSubscribe onNext* (onError | onComplete)?

这意味着onSubscribe方法总是被调用,后面跟着一个可能的无限数量onNext方法调用(因为订阅者的请求)。如果失败的话,后跟一个onError方法调用,或当没有更多的元素可用时,是一个onComplete方法调用,只要这个Subscription(订阅关系)没有被取消。



//
Glossary
//



术语,释义
Signal,本义是信号。作为一个名词,指的是这些方法onSubscribe,onNext,onComplete,onError,request(n)或cancel中的一个。作为一个动词,指的是调用这些方法中的一个。

表面上可以理解为发信号进行通知,本质上也是通过方法调用来实现的。

Demand,本义是需求。作为一个名词,指的是一个订阅者(向发布者)请求的一定数量的元素,它还没有被发布者分发。作为一个动词,指的是请求更多元素的行为动作。

可以看作是订阅者向发布者发出的需求/动作,想要获取更多的元素。发布者暂时还没有回应。

Synchronous(ly),本义是同步的。指的是在调用线程上执行(没有新开线程)。

Return normally,本义是正常返回。指的是仅返回已声明过的类型的值给调用者。如果想发送一个失败给订阅者,唯一合法的方式是通过onError(回调)方法。

Responsivity,本义是响应度。指的是已准备就绪有能力来做出响应。在这个文档里用来指示不同的组件不应该互相削弱响应的能力。

Non-obstructing(堵塞),本义是不堵塞。指的是描述一个方法的质量(品质),即在调用线程上尽可能快地执行完。这意味着,例如,避免重的计算和其它将拖住调用者线程执行的事情(因为没有新开线程)。

Terminal state,本义是终止状态。对于一个发布者,指的是当onComplete或者onError已经被调用。对于一个订阅者,指的是当一个onComplete或onError(回调方法)已经收到。

NOP,指的是执行对于调用线程来说没有可检测到的影响,能够像这样安全地被调用任意次。

External synchronization,本义是外部同步。为了线程安全的目的,协调访问在这个规范里定义的结构之外被实现,使用的技术像但不限于atomics,monitors或locks。

Thread-safe,能够安全地被同步或异步调用,不需要外部的同步来确保程序的正确性。


下一篇:JVM自动内存管理机制——Java内存区域(下)

评论留言

还没有评论留言,赶紧来抢楼吧~~

Erlo大厅()

* 这里是“吐槽厅”,所有人可看,只保留当天信息。

  • Erlo.vip2019-08-21 05:35:31Hello、欢迎使用吐槽厅,这里是个吐槽的地方。
  • 首页 笔记分享 案例展示 ERLO 搜索
    鼠标试试
    返回顶部