原文地址:http://projectreactor.io/docs/reference/

Reactor简介

Reactor是一个基础库,用在构建实时数据流应用、要求有容错和低延迟至毫秒、纳秒、皮秒的服务。

— PrefaceTL;DR

什么是Reactor?

  让我们大致了解一下Reactor。在你使用喜欢的搜索敲入一些关键词如Reactive、spring Reactive、Asynchronous java或者仅仅是"What the heck is Reactor?".简而言之,Reactor是一个轻量级的JVM基础库,它可以帮助我们构建的服务和应用高效而异步的传递消息。

高效的含义是什么呢?
传递一个消息从A到B时GC产生的内存很小或者完全没有。
当消费者处理消息的速度低于生产者产生消息的速度时产生了溢出时,必须尽快处理。
尽可能的提供无锁的异步流。

  据以往的经验来看,我们知道异步编程是困难的,特别是当一个平台提供了很多选项如JVM。

Reactor瞄准绝大部分场景中真正的无阻塞,并且提供了一组比原生Jdk的java.util.concurrent库更高效的API。Reactor也提供了一个可选性(不建议使用):

  阻塞等待:如Future.get()。

Unsafe数据获取:如ReentrantLock.lock()。

  异常抛出:如try ..catch ...finally

  同步阻塞:如 syschronized

  Wrapper配置(GC压力):例如 new Wrapper<T>(event)

让我们先使用一个纯正的Executor方法:

private ExecutorService  threadPool = Executors.newFixedThreadPool(8);

final List<T> batches = new ArrayList<T>();

Callable<T> t = new Callable<T>() {  //1

    public T run() {
synchronized(batches) { //2
T result = callDatabase(msg); //3
batches.add(result);
return result;
}
}
}; Future<T> f = threadPool.submit(t); //4
T result = f.get() //5

  1.分配回调方法---可能会导致gc压力。

  2.Synchronization将强制对每个线程停止检查。

  3. 存在消费者的消费能力低于生产者生产能力的隐患。

  4. 使用线程池将task传递到目标线程--肯定通过FutureTask给gc造成压力。

  5. 阻塞直至callDatabase()响应。

从上述的简单示例中,容易看出扩展性会受到严重的影响。

  不断分配的对象将导致gc停止工作,特别是耗时比较多的大任务时。当一个gc停止工作时将会从降低全局的性能。

  队列默认情况下长度是不受限制的。任务会堆积到数据库中。

       后台日志不是一个内存泄露的地方,但是副作用就比较烦人了:在gc暂停工作时需要扫描更多对象;损失数据重要bit的风险;等等。

    经典链接Queue分配节点时产生的内存压力。

  使用阻塞方式应答请求时发生恶性循环。

    阻塞方式应答导致生产者效率慢下来。实际上,因为需要提交更多任务时等待响应,流程变成了基本的同步方式。

    同数据存储的通信异常将以不友好的形式传递到生产者,通过线程边界来分离工作,这使容错的协商变的比较容易。

  完全的、真正的非阻塞比较难以实现---特别是有比较时髦名称的分布式系统中如微服务架构。然而,Reactor却没有妥协,它试图利用可用的最佳模式来使开发者不必觉得像是在写一个数学论文而仅仅是一个微服务(nanservice)。

  没有什么比较光更快的了(除了流言蜚语和病毒猫视频),在某些方面,延迟是每个真实世界的系统必须关注的。为此:

反应器提供了一个框架,可以帮助你减轻恶心的延迟引起的副作用,在应用程序中使用最小的开销:使用一些灵活的结构,通过在启动时预先分配在运行时的分配数据结构来避免分配问题。

限制主消息传送结构,因而不会导致任务无限的累积。

利用流行的模式例如Reactive和事件驱动架构来提供一个包含应答的非阻塞的、端对端流。

实现了最新的Reactive流标准,通过不发送多于当前容量的请求来使受限的结构更有效率。

使用这些概念到进程间通信,提供了理解控制流的非阻塞IO驱动。 对开发者暴露功能API,帮助开发者使用一个无副作用的方式组织代码,也帮助你确定在什么场景下你是线程安全和具有容错性的。

项目简介:

  该项目始于2012年,孕育时间较长。2013年出现Reactor1.x版本。该版本成功部署到不同的组织,不仅有开源组织如MeltDown、还有商业机构如Pivotal RTI。2014年我们实现了新的"Reactive流标准",并在2015年的4月开始了版本2.0的大规模重构目标。Reactive流标准拉近了分发机制的鸿沟:控制多少线程传递多少数据。

  同时我们也决定重新调整我们的一些事件驱动和任务协调API的来应对日益流行、记录的reactive扩展。

  Reactor由Pivotal赞助支持,有两个核心提交者。因为Pivotal同时也是spring框架的东家,我们的很多同事也是不同spring项目的核心贡献者,所以我们也提供从Reactor到spring的集成同时也支持spring框架的一些重要功能如spring消息模块的STOMP代理。也就是说,我们不会强迫仅仅想使用Reactor的人去适应spring。我们保留了一个大容量Reactive的内嵌工具。事实上,Reactor的目标之一是在你解决异步和功能性问题时保持公正的态度。

  Reactor遵循Apache 2.0 licensed ,可以通过 GitHub获取。

  使用要求:

  Reactor需要jdk7及以上版本。

    但完整的功能组合表达式需要java8的lambdas支持。

    作为后备,支持spring clojure和groovy的扩展。

  Reactor需要jvm支持Unsafe方式获取(如:android不支持)时才能表现最全的功能。

    当Unsafe获取不支持是所有基于RingBuffer的特定将不能工作。

  Reactor打包成传统的jar形式存在于maven中央库中,可以使用你喜欢的工具来拉取这个依赖包。

  架构总览

Reactor基本代码划分为几个子模块,这样你可以单独使用某一模块而抛弃不需要的模块。

下述是一些使用Reactor模块和其它混合的Reactive技术示例,完成异步目标:

  • Spring XD + Reactor-Net (Core/Stream) : 使用Reactor 作为Sink/Source IO 驱动.

  • Grails | Spring + Reactor-Stream (Core) : 使用Stream和 Promise作为后台处理程序。

  • Spring Data + Reactor-Bus (Core) : 生产数据库事件(Save/Delete/…​).

  • Spring集成Java DSL + Reactor Stream (Core) : Microbatch MessageChannel from Spring Integration.

  • RxJavaReactiveStreams + RxJava + Reactor-Core : Combine rich composition with efficient asynchronous IO Processor

  • RxJavaReactiveStreams + RxJava + Reactor-Net (Core/Stream) : Compose input data with RxJava and gate with Async IO drivers.

 Reactive stream

  Reactive stream是一个新的标准,不同的厂商和技术组织包括Netflix,oracle,Pivotal,TypeSafe支持这个标准。该标准有望被java9或者以后的版本的标准收录进去。

  该标准的目标是提供一种同步或者异步的具有控制流机制的数据序列。这个标准是轻量级的,第一个目标是JVM。它提供了4个java接口,一个Tck和一系列的示例。根据需要,4个java接口的实现非常直接,这个项目的内涵是Tck对操作的校验。

                              图三 Reactive stream协约

Reactive Streams接口
org.reactivestreams.Pubslisher: 数据源(从0到N个数据,n是任意的).它提供两个可选的中断事件:error和completion。 org.reactivestreams.Subscriber: 数据序列的消费者(从0到N个数据,n是任意的).它在初始化时接收一个Subscription,subscription获取Subscriber将要处理多少数据。 与其它数据时序信号交互的其它回调有: next (新消息)和可选的completion/error.
org.reactivestreams.Subscription:在初始化时传给Subscriber的一个小的追踪器。.它控制着我们准备消费掉多少数据和什么时候停止消费(取消).
org.reactivestreams.Processor: 既是Subscriber和Publisher的组件标识!

          图四:Reactive Stream发布协约

通过传递Subscriber,一个请求数据从subscriber到publisher有两种方式:
无限制的: 在订阅时, 仅调用Subscription的request(Long.MAX_VALUE)方法. 有限制的: 在订阅时, 保留subscription的引用,并且当subscriber准备处理数据时调用request(long)方法。   通常, 在订阅时Subscribers将请求一组初始数据或者甚至1个数据。   然后,onNext认为执行成功(例如后面的Commit, Flush等等​), 请求更多的数据。   建议使用线性组的请求。为避免请求重叠,例如每次下次请求时请求10个或者更多的数据。

表1 目前为止,Reactor直接使用的Reactive stream接口及实现

Reactive Streams Reactor模块 实现 说明

Processor

reactor-core, reactor-stream

reactor.core.processor.*, reactor.rx.*

在core模块,提供了RingBuffer处理器,在stream模块,提供了一整组操作和Broadcaster。

Publisher

reactor-core, reactor-bus, reactor-stream, reactor-net

reactor.core.processor.*, reactor.rx.stream.*, reactor.rx.action.*, reactor.io.net.*

在core模块,处理器继承了Publisher.在bus模块,发布一个不限制的路由事件,在stream模块,stream扩展直接继承Publisher. 在net模块,Chanel继承了Publisher来消费请求数据,同时也提供了具有flush和close的回调的providers.

Subscriber

reactor-core, reactor-bus, reactor-stream, reactor-net

reactor.core.processor.*, reactor.bus.EventBus.*, reactor.rx.action.*, reactor.io.net.impl.*

在core模块,处理器继承了Subscriber. 在bus模块,提供了无限制的Publisher/Subscriber能力.在stream模块,Subscribers计算特定的回调行为.在Net模块,subscriber的IO层实现处理写、关闭和flush.

Subscription

reactor-stream, reactor-net

reactor.rx.subscription.*, reactor.io.net.impl.*

在stream模块, 提供了一个优化过的PushSubscriptions和 buffering-ready ReactiveSubscription. 在Net模块, 使用自定义Subscription实现背压的方式实现异步IO读。

从reactor 2启动时我们就一直遵循这个标准,并且随着标准的改变而改变直到1.0.0正式版准备发布。现在可以通过maven中央库及其流行的镜像可以找到该标准,你将发现它作为过渡,依赖于reactor-core模块。

Reactive扩展

  Reactive扩展或者通常称作Rx,是一种定义完备的功能api,这些api扩展了观察者模式到一个史诗的程度。

  Rx模式支持实现了使用少数设计的关键字来处理Reactive 数据序列:

    使用回调链来抽象实时及延迟:当可以获得到数据时调用。

    抽象了一直使用的线程模式:同步或者异步仅仅是我们处理的Observable/Stream。

    控制错误传递及停止:错误和完成信号及数据的有效负载信号传递到链中。

    在多个预先定义的api中解决了多个扩展-聚合及其它组合问题。

  Reactive扩展的标准Jvm实现是RxJava。它提供了一个功能丰富的Api。

  Reactor 2 提供了一个特定模块实现了Reactive扩展的一部分功能。建议需要使用Reactive stream全部功能的用户使用RxJava。最后,当组合完整的RxJava系统时,用户可以从Reactor提供的强大的异步和IO的中获益。

  表2:Rx和Reactor stream的不同点:

rx reactor-stream 说明

Observable

reactor.rx.Stream

Reactive Stream Publisher的实现

Operator

reactor.rx.action.Action

Reactive Stream Processor的实现

Observable with 1 data at most

reactor.rx.Promise

返回唯一结果的类型,  Reactive Stream Processor实现并提供了可选的异步分发功能。

Factory API (just, from, merge…​.)

reactor.rx.Streams

和core模块的 data-focused 子类一样, 返回 Stream

Functional API (map, filter, take…​.)

reactor.rx.Stream

和core模块的data-focused 子类一样, 返回Stream

Schedulers

reactor.core.Dispatcher, org.reactivestreams.Processor

Reactor Stream计算无限制的共享Dispatcher或者有限的Processor的操作。

Observable.observeOn()

Stream.dispatchOn()

只是dispatcher参数的一个适配命名。

reactor官方文档译文(1)Reactor简介的更多相关文章

  1. reactor官方文档译文(2)Reactor-core模块

    You should never do your asynchronous work alone. — Jon Brisbin 完成Reactor 1后写到 You should never do y ...

  2. Extjs6官方文档译文——应用架构简介(MVC,MVVM)

    应用架构简介 Extjs 同时提供对于MVC和MVVM应用架构的支持.这两个架构方式共享某些概念,而且都旨在沿着逻辑层面划分应用程序代码.每种方法在选择如何划分应用组件上都有其各自的优势. 本指南的目 ...

  3. 10分钟了解 pandas - pandas官方文档译文 [原创]

    10 Minutes to pandas 英文原文:https://pandas.pydata.org/pandas-docs/stable/10min.html 版本:pandas 0.23.4 采 ...

  4. App开发架构指南(谷歌官方文档译文)

    这篇文章面向的是已经掌握app开发基本知识,想知道如何开发健壮app的读者. 注:本指南假设读者对 Android Framework 已经很熟悉.如果你还是app开发的新手,请查看 Getting ...

  5. PEP 324 subprocess 新的进程模块 -- Python官方文档译文 [原创]

    PEP 324 -- subprocess 新的进程模块(subprocess - New process module) 英文原文:https://www.python.org/dev/peps/p ...

  6. iOS·官方文档译文框架源码注解

    导语

  7. Apple官方文档译文GitHub框架源码注解

    引导

  8. Daphile 安装手册 -- 官方文档译文 [原创]

    Daphile 安装手册(Daphile Installation) 英文原文:https://www.daphile.com/download/DaphileInstallation.pdf 采集日 ...

  9. Daphile FAQ -- 官方文档译文 [原创]

    Daphile FAQ 英文原文:https://www.daphile.com/download/FAQ.txt 采集日期:2021-01-03 常见问题解答:(FAQ) Q1:没有声音.Daphi ...

随机推荐

  1. [WinForm] 使用 WebBrowser 操作 HTML 頁面的 Element-摘自网络

    前言 在 Window Form 應用程式如果需要瀏覽網頁時可以崁入 WebBrowser 控制項,但如果需要操作崁入的 HTML 的網頁元素,就需要額外的操作,以下紀錄幾種操作 HTML 元素的方法 ...

  2. 自然对数e

    上学时课本里提到过,有一种以无理数e=2.71828--为底数的对数,称为自然对数.当时老师并没有讲明白这是个啥东西.并且还有一个很奇怪的极限,也是靠记忆的,完全不理解. \[\lim_{n\to\i ...

  3. datareader几种用法总结

    1.本人常用: if (reader["字段名"] != DBNull.Value) { userRegisterInfo.OrgCode = reader["字段名&q ...

  4. POJ1185状态压缩DP

    难得的中文题. POJ1185http://poj.org/problem?id=1185 方法就是用DP[i][r][p]表示第i行状态为r,第i-1行状态是p时的最多个数.而这里p受到r的限制,而 ...

  5. sqlserver 自增字段修改为普通主键字段

    --增加备份字段alter Table tableName add columnNameBak bigint ; --将主键自增字段 赋值到备份字段update tableNameset column ...

  6. Linux下修改hostname

    我维护两三个机房的数十台机器,开发用机器,运营用机器,自己工作机器也是ubuntu,有时开很多ssh,干的还是同样的事情,很容易搞混.所以需要一目了然的知道某台机器的情况,避免犯晕.这就需要修改主机名 ...

  7. nhibernate操作sql2008数据库(添加数据失败)

    今天遇到一错误困了我一天,如此痛恨,遂记录于此: nhibernate框架+MVC模式搭的项目,添加数据时报错: "could not insert: [KXRMallManage.Mode ...

  8. 3.依赖倒置原则(Dependence Inversion Principle)

    1.定义 高层模块不应该依赖于低层模块,二者都应该依赖于抽象:抽象不应该依赖细节:细节应该依赖抽象. 2.定义解读 依赖倒置原则在程序编码中经常运用,其核心思想就是面向接口编程,高层模块不应该依赖低层 ...

  9. 【css hack】正是我所找的,帮了大忙啊

    (从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期2014-03-05) 各个浏览器单独设置属性 IE6:能识别下划线 “_” 和 星号 “*“,不能识别 “!important”    ...

  10. ANDROID FRAMENT的切换(解决REPLACE的低效)

    http://www.cnblogs.com/android-joker/p/4414891.html 在项目中切换Fragment,一直都是用replace()方法来替换Fragment.但是这样做 ...