RxJava 团队历时 18 个月的开发周期后发布了其响应式 Java 框架的 2.0 版本。RxJava 是 ReactiveX 库和框架的一部分,用他们的话来说就是“观察者模式、迭代器模式和函数式编程的最完美融合”。项目组发布的“ 2.0 版本的不同之处”是给已经熟悉 RxJava 1.x 版本的开发者的很好的阅读指南。
RxJava 2.0 可以说是 RxJava 的全新实现。该版本基于响应式流规范,提供了异步数据流处理非阻塞背压、目标运行环境(JVM 和 JavaScript)以及网络协议的一套标准。
响应式实现由发布者、订阅者、订阅数据流、获取下一个数据流、处理错误以及关闭连接的概念组成。
响应式流规范将作为 java.util.concurrent.Flow 出现在 JDK 9 中。以下接口对应于响应式流规范。正如你所看到的,规范并不大,只包含了四个接口:
- Flow.Processor :同时充当订阅者和发布者的组件。
- Flow.Publisher :订阅者接收的项目(及相关控制信息)的生成者。
- Flow.Subscriber :消息的接收者。
- Flow.Subscription :连接 Flow.Publisher 和 Flow.Subscriber 的消息控件。
Spring Framework 5 也是响应式的。想要了解其工作方式,请参考Josh Long 的 Spring Framework 5.0 的功能响应式端点。
为了解有关 RxJava 2.0 的更多信息,InfoQ 采访了 RxJava 2.0 的主要贡献者 David Karnok 。
InfoQ:首先恭喜成功发布 RxJava 2.0!18 个月的艰辛工作,这简直是一个壮举。这个版本什么地方让你最感到骄傲?
David Karnok:谢谢!在某种程度上,我希望它不要开发这么久。在 RxJava 的原作者 Ben Christensen 离开的时候我们经历了 10 个月的停顿,那段时间里 Netflix 没有一个人推动这个项目的进展。我相信会有很多人同意自我六月份接管这个项目之后,一切变得明朗起来。我很高兴我对于更先进、更高性能的响应式流的研究得到了好的成果,RxJava 2 是它最好的答卷。
InfoQ:RxJava 2.0 有何不同,它将怎么帮助开发人员?
Karnok:版本 1 和版本 2 区别很多,我不能在这里列举所有的不同之处,但用户可以访问我们专门创建的 wiki 页面了解更多信息。大体来说,我们现在支持标准响应式流规范,在许多地方都显著地缩减了开销,不再允许空值,根据类型或背压支持的不同拆分库并在基本响应类型间进行显式交互操作。
InfoQ:RxJava 在什么地方运用最广泛?(比如说 IoT、实时数据处理等等)
Karnok:基于我得到的反馈,我发现 RxJava 在 Android 社区运用最为广泛。我相信 Project Reactor 和 Akka 主导了服务器端。我并没有具体看到过 IoT 提及或使用 RxJava(它需要 Java)的具体例子,也许它们使用了一些在其平台上可行的其他响应式库。实时数据处理方面,人们仍然倾向于使用其他解决方法,其中大多数不是真正的响应式,我不知道有什么提供商(也许是 Pivotal)正在推动响应式在该领域的发展。
InfoQ:RxJava 比起其他环境能给 Android 提供什么更好的帮助?
Karnok:据我所知,Android 非常想“帮助”他们的用户在仅仅使用 Android 工具,如 AsyncTask、Looper/Handler 等等的情况下解决异步和并发问题。
不幸的是,其设计和使用体验并不方便,由于 Android 开发人员往往难以理解或预测其设计方法,他们的使用感并不佳。这很容易造成回调地狱,并造成主线程异步操作的困难。
RxJava 的设计(继承于 Microsoft 的 ReactiveX 的设计)是面向数据流并正交化的,当进行数据处理的时候就会执行动作。此外,错误处理和报告是流的关键部分。使用 AsyncTask,你必须手动解决错误传递模式并取消挂起的任务,但是 RxJava 却能自动处理这一部分工作。
实际上,有一个流在后台查询这几个服务,在主线程中呈现的结果可以在 RxJava(+Retrofit) 中用几行进行表示,简单的屏幕旋转操作就可以立即取消服务调用。
这对于 Android 开发人员来说是巨大的生产力提升,简单的操作就可以帮助他们更好地实现整个响应式编程模式转换所需的复杂的学习曲线。也许到最后,RxJava 对于 Android 会变得至关重要,因为它减少了移动应用程序业务中个体开发人员、创业公司和小公司的“上市时间”。
在我看来,桌面端 / 服务器端 Java 并没有可比性。人们启动 ExecutorService 并等待 Future.get(),知道 SwingUtilities.invokeLater 可以将数据发送回 GUI 线程,否则 Servlet API(每个请求只有一个线程(pre 3.0))会自然地阻塞 APIs(数据库、服务调用)。
桌面端 / 服务器端人员对他们的服务提供的非阻塞设计的性能优势更感兴趣(而并非可以如何简便地编写服务)。然而,与 Android 开发不同,仅仅使用 RxJava 是不够的,很多人都迫切希望有完整的框架可以帮助他们实现业务逻辑,因为没有用于非阻塞 web 服务的“恰当”标准可以代替 Servlet API。(确实有 Spring (~Boot) 和 Play,但我并不想现在使用这些新潮的东西。)
InfoQ:HTTP 是一种同步协议,当使用微服务的时候可能会造成很大的背压。像 Akka 和 Apache Kafka 这样的流平台可以帮助解决这个问题。RxJava 2.0 是否也能自动处理背压问题?
Karnok:RxJava 2 的 Flowable 类型实现了响应式流接口和规范,并可以支持背压。然而,Java 层面的背压和网络级别的背压大相径庭。对我们来说,背压代表着在不同阶段管道可以传送多少对象,这些对象的类型和大小可能各不相同。而在网络层面上来说,往往处理固定大小的包,缺少先前传送包的确认显示背压。在经典设置中,网络背压在 Java 层面上显示为阻塞调用,直到所有数据片段都被写入后才会返回。有类似 Netty 的非阻塞设置,其中阻塞被隐式缓冲取代,并且据我所知,只有单独、非统一和非响应式流的兼容方式可以处理它们(比如说检查 canWrite 中什么必须周期性地重试)。有库在尝试嫁接 RxNetty 和一些 Spring,它们也取得了不同程度的成功。
InfoQ:你是否认为响应式架构可以处理大量的流量和实时数据?
Karnok:这取决于问题的复杂性。比如说,如果你的任务是计算大数据源中的字符数,那会有更快、更专用于此的方法。如果你的任务是在传入数据流的服务上生成结果,以返回更详细的响应式解决方案,那这个方法就足以解决问题。据我所知,响应式流的大多数库和框架都是为吞吐量而设计的,而不是为延迟而设计的。比如说,在高频率交易中,可预测的延迟非常重要,可以很容易地被 Aeron 实现,但这不是 RxJava 主要要解决的问题,因为不可预测延迟。
InfoQ:HTTP/2 是否能解决 HTTP/1.1 中可扩展性的问题?
Karnok:这与 RxJava 没什么大关系,我个人没有使用过 HTTP/2,我仅仅阅读过其规范。通过相同信道的多路复用取得了一定程度上的成功,但是对于显示背压的支持(比如说即使可以通过网络传送,客户端仍然无法处理卷中的数据)还有待解决。我并不清楚所有的技术细节,但我相信 Spring Reactive Web 确实可以支持 HTTP/2 传输,它保留了响应式抽象的复杂性,所以你可以在 RxJava 2 和 Reactor 3 中表示你的处理管道。
InfoQ:Java 9 预计将实现一些响应式功能。这个规范是否完整?
Karnok:并不。Java 9 仅仅会实现 4 个 Java 接口,共有 7 个方法。没有类似于流或类似于 Rx 的 API,也没用任何基于 JDK 的功能。
InfoQ:如果建立在 JDK 上是否可以避免使用 RxJava?
Karnok:不,我相信对于真正的、成熟的库(如 RxJava)的需求会越来越多。一旦工具链达到 Java 9,我们肯定会提供适配器,我们也会基于 Java 9 的功能 (VarHandles) 调整或重写 RxJava 3。
我担心的是,一旦 Java 9 推出,会有很多个人或是企业尝试写自己的库,“市场”中会充斥着很多低质量的解决方案,更何况例如“RxJava 与 X 有何不同”这样的问题会层出不穷。
我知道这种情况已经发生于响应式流中,有一些库和框架宣传自己是 RS,但并不能提供基于它的服务。我(可能我的观点有些偏激)觉得 RxJava 2 是最优的基于响应式流的解决方案。
InfoQ:RxJava 的下一步规划如何?
Karnok:在开发 RxJava 2 的时候,我们有很优秀的审核人,比如 Jake Wharton。不幸的是,尽管我们很努力,开发者预览版和候选版本并没有得到足够的关注,一些小的问题和疏漏还是进入了最终版本。我不期望在未来几个月能解决主要的问题,但我们将持续修复版本 1 和 2,并引入新的操作者来支持我们的用户群。一些附带的库比如 RxAndroid 提供了 RxJava 2 的兼容版本,但大多数其他的库还尚未推出兼容版本。有关于 RxJava,我计划在六个月内退出 RxJava 1(也就是说只修复漏洞),部分原因是因为我一个人维护的负担太重了,鼓励大家转换到 RxJava 2。关于 RxJava 3 还没有具体的计划。有讨论说要根据类型或背压支持的不同拆分库,并制作所谓的运算符 - 融合元素(可以帮助我们提高性能),响应流规范的标准扩展。
查看英文原文: RxJava 2.0 Released with Support for Reactive Streams Specification
评论