可观察与可流动rxJava2


127

我一直在寻找新的rx java 2,但我不确定我是否已经明白了这个主意backpressure...

我知道我们所拥有的Observable并没有backpressure支持Flowable

因此,基于例如,可以说我有flowableinterval

        Flowable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

在大约128个值之后,这将崩溃,这很明显我消耗的速度比获取项目要慢。

但是,我们有相同的 Observable

     Observable.interval(1, TimeUnit.MILLISECONDS, Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    // do smth
                }
            });

即使我延迟使用它,它仍然完全不会崩溃。为了Flowable工作,可以说我放了一个onBackpressureDrop运算符,崩溃已经消失了,但是并不是所有值都被发出。

因此,我目前在脑海中找不到答案的基本问题是,为什么我应该关心backpressure何时可以使用Plain Observable仍会接收所有值而无需管理buffer?或者,也许从另一方面来看,backpressure我有什么优势可以帮助我管理和处理消费?


Answers:


122

实际上,反压显示的是有界缓冲区,Flowable.observeOn缓冲区中包含128个元素,其流失速度与dowstream可以吸收的速度一样快。您可以单独增加此缓冲区的大小以处理突发性源,并且所有反压管理实践仍从1.x开始适用。Observable.observeOn具有无限制的缓冲区,该缓冲区会不断收集元素,并且您的应用程序可能会耗尽内存。

您可以使用Observable例如:

  • 处理GUI事件
  • 使用短序列(总共少于1000个元素)

您可以使用Flowable例如:

  • 冷源和非定时源
  • 发电机一样的来源
  • 网络和数据库访问器

由于这已经拿出的另一个问题 -它是正确的,更多的限制类型,如MaybeSingle并且Completable可以随时用来代替的Flowable,当他们在语义上合适吗?
david.mihola

1
是的,MaybeSingle,和Completable远远太小,有任何需要背压的概念。生产者放出物品的速度绝不可能超过消耗的速度,因为生产或消费的物品将是0-1。
AndrewF

也许我不对,但对我而言,应将Flowable和Observable的示例互换。
Yura Galavay

我认为在这个问题上他缺少我们需要提供给Flowable的背压策略,这解释了为什么会丢失缺少的背压异常,也解释了为什么在应用.onBackpressureDrop()之后该异常消失了。对于Observable,由于它没有这一策略且无法提供,因此由于OOM而导致稍后失败
Haomin

110

背压是指您的可观察者(发布者)创建的事件多于订阅者可以处理的事件。因此,您可以使订户丢失事件,或者可以获取大量事件,最终导致内存不足。 Flowable考虑到背压。 Observable才不是。而已。

它使我想起了一个漏斗,当漏斗中有太多液体溢出时。Flowable有助于避免这种情况的发生:

具有巨大的背压:

在此处输入图片说明

但是使用flowable,反压要小得多:

在此处输入图片说明

Rxjava2根据您的用例可以使用一些反压策略。通过策略,我的意思是Rxjava2提供了一种方法来处理由于溢出(背压)而无法处理的对象。

这里是策略。 我不会全部介绍它们,但是例如,如果您不想担心溢出的物品,可以使用如下放置策略:

observable.toFlowable(BackpressureStrategy.DROP)

据我所知,队列上应该有128个项目的限制,之后可能会有溢出(背压)。即使不是128,也接近该数字。希望这对某人有帮助。

如果您需要将缓冲区大小从128更改为看起来像这样,可以这样做(但要注意任何内存限制:

myObservable.toFlowable(BackpressureStrategy.MISSING).buffer(256); //but using MISSING might be slower.  

在软件开发中,背压策略通常意味着您告诉发射器放慢速度,因为用户无法处理发射事件的速度。


我一直认为反压是一系列机制的名称,它可以让消费者通知生产者放慢速度……
kboom,

可能是这样。是的
j2emanue

使用Flowable是否有不利之处?
IgorGanapolsky '18

这些图像对我说谎。放弃事件不会以“更多的钱”为底。
EpicPandaForce

1
@ j2emanue,您混淆了运算符和Flowable.buffer(int)运算符的缓冲区大小。请cafefully阅读的javadoc,并相应地解决您的答案:reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html
托梅克

15

Flowable发出128个值而没有反压处理后崩溃的事实并不意味着它总是在恰好是128个值之后崩溃:有时它会在10个值之后崩溃,有时它根本不会崩溃。我相信这是您尝试使用该示例时Observable发生的事情-碰巧没有反向压力,因此您的代码正常运行,下次可能不会。RxJava 2中的不同之处在于,不再有Observables中的反压概念,也没有办法解决它。如果您正在设计一个可能需要显式背压处理的反应式序列,那么这Flowable是您的最佳选择。


是的,我观察到有时它会在减少值之后破裂,有时却没有。但是,再次举例来说,如果我仅在interval没有处理的情况下进行操作backpressure,我会期待一些怪异的行为或问题吗?
user2141889 16-10-29

如果您确定在特定的Observable序列中不可能发生背压问题-那么我想可以忽略背压。
Egor,2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.