RxJava VS Reactor

随着web应用的发展,人们提出了响应式的概念,在应用高负载,高并发的时候仍然有良好的用户体验,能够尽可能的实时返回数据。

The need for a non-blocking web stack to handle concurrency with a small number of threads and scale with fewer hardware resources. Servlet 3.1 did provide an API for non-blocking I/O.

意思是使用更少的线程数和更少的硬件资源来处理大量的并发请求。

目前市场上比较流行的有几种,RxJava,Akka,Vert.x,Reactor。最常使用的两种框架,并且实现了响应式编程规范的是RxJava和Reactor。

两者之间有什么区别呢?

API -> Reactor

FlowableFluxAPI很相似都支持,ReactiveX常见的那些操作符。map,filter,flatmap等等,具体操作符列表:http://reactivex.io/documentation/operators.html

在Java版本上:

  • RxJava2.x必须至此Java 6,因为它Rxjava在安卓中用的很多
  • Reactor则至少要求Java 8. 其内部利用了很多新版Java的特性。并且还可以方便的转换为:CompletableFuturejava.util.stream.StreamOptional

Reactor胜出一票

Checked exceptions -> RxJava

  • Reactor使用Java标准的functional类型,如java.util.function.Function
  • RxJava使用自己设计的函数类型。io.reactivex.functions.Function

对于JDK自带的Function,checked exception则不能编译通过,效果如下图。使用Reactor的时候必须要处理这些异常。

这一点设计的好坏上,看用户习惯,但RxJava体验上可能更好一些,用户选择是否要捕获异常,Reactor强制捕获异常。

image-20200113135725803
image-20200113135702010

RxJava胜出0.5票

类型 -> RxJava

Reactor只支持,Mono和Flux类型,而RxJava支持CompletableMayBeSingleObservableFlowable

其中Mono和MayBe对应,Flowable和Flux对应。Reactor不支持其它的类型,也就意味着在一些场景下Reactor并不能很好的支持。

  • 难道Mono一定要发射一个值?能不能不发射值
  • 能不能不想要背压的支持?

在各种常见的处理上,RxJava处理的歧义比Reactor更少一些,并且支持更多的类型。

RxJava胜出一票

Testing -> Reactor

在多线程程序测试上,我们可能想要使用一个虚拟的线程调度器来模拟时钟。RxJava提供了TestScheduler,但是可能会出现多次传递TestScheduler的场景,这个时候代码就更容易陷入一团乱。

对于Reactor则是使用了withVirtualTime,底层会自动的进行替换,提升代码的可读性。

Reactor胜出0.5票

Debugging -> Reactor

Reactor添加了一个很好的调试特性:

Hooks.onOperatorDebug();

在应用之前加上这一行代码,可以跟踪数据流的流动,看一个例子。

public class FluxDemo {
    public static void main(String[] args) {

        Hooks.onOperatorDebug();

        Mono<Long> totalTxtSize = Flux
                .just("/tmp", "/home", "/404")
                .map(File::new)
                .concatMap(file -> Flux.just(file.listFiles()))
                .filter(File::isFile)
                .filter(file -> file.getName().endsWith(".txt"))
                .map(File::length)
                .reduce(0L, Math::addExact);

        totalTxtSize.subscribe(System.out::println);
    }
}

不加Hooks调试。

image-20200113141212664

加上Hooks调试:

image-20200113141257216

响应式编程在调试的时候增加了一定的难度,而Reactor带来的特性一定程度上减轻了困难。

Reactor胜出一票

Spring支持 -> Reactor

Reactor本身是Spring开发人员弄出来的东西,可以与Spring无缝集成,当前Spring新推出的Spring Webflux更是基于Reactor。

作为Java开发人员,Spring可以说是每日都要去使用的东西,Reactor都得到了官方的支持,为什么要使用RxJava呢?

Reactor胜出一票

Android开发 -> RxJava

RxJava在安卓开发者中非常的流行,优雅的解决了两个问题,并且现在有RxAndroid的库可以使用:

  • 避免了UI的事件回调地狱,将用户UI事件建模为事件流
  • 容易的切换线程,避免了IO线程运行在UI线程上

目前安卓开发者只能选择RxJava,并且RxJava在Android上已经运行的很稳定。

RxJava胜出一票

成熟度 -> RxJava

RxJava目前相比与Reactor更加成熟并且得到市场的认可,参考安卓,其目前被使用的时间更久,关于RxJava的书籍更多,并且也有很多的响应式框架是基于RxJava来做的。

成熟度上目前RxJava胜出一票

最后

两者不相上下

  • 如果是Web开发,可以考虑使用Reactor,毕竟Spring的亲儿子,而且Reactor使用了最新版的一些Java特性,效率上,安全性上,稍微好一点。
  • 如果是Android开发,那么选择RxJava,因为RxJava对Android的支持一直都很好
  • 如果现在已经在使用两种中的其一了,那么继续使用,无需更换

参考:

https://www.reactivesystems.eu/2017/01/31/things-i-wish-i-knew-when-i-started-building-reactive-systems.html

https://www.javacodegeeks.com/2018/08/frameworks-toolkits-make-java-reactive-rxjava-spring-reactor-akka-vert-x-overview.html

https://www.nurkiewicz.com/2019/02/rxjava-vs-reactor.html

推荐阅读更多精彩内容