1. 背压
在 RxJava 中,会遇到被观察者发送消息太快以至于它的操作符或者订阅者不能及时处理相关的消息,这就是典型的背压(Back Pressure)场景。背压是指在异步场景下,背光插着发送事件速度远快于观察者处理的速度,从而导致下游的 buffer 溢出。 首先,背压必须是在异步的场景下才会出现,即被观察者和观察者处于不同的线程中。 其次,RxJava 是基于 Push 模型的。对于 Pull 模型而言,当消费者请求数据的时候,如果生产者比较慢,则消费者会阻塞等待。如果生产者比较快,则生产者会等待消费者处理完后再生产新的数据,所以不会出现背压的情况。然而在 RxJava 中,只要生产者数据准备好了就会发射出去。如果生产者比较慢,则消费者会等待新的数据到来。如果生产者比较快,则会有很多数据发射给消费者,而不管消费者当前有没有能力处理数据,这样就会导致背压。 在 RxJava 2.x 中,只有新增的 Flowable 类型是支持背压的,并且 Flowable 很多操作符内部都使用了背压策略,从而避免过多的数据填满内部的队列。 在 RxJava 1.x 中,有很多事件因为不能被正确的背压,从而草除 MissingBackpressureException。在 RxJava 1.x 中的 observerOn,由于切换了观察者的线程,因此内部实现用队列存储事件。
2. RxJava 2.x 的背压策略
在 RxJava 2.x 中,Observable 不再支持背压,而是改用 Flowable 来专门支持背压。默认队列大小为 128
,别切要求所有的操作符强制支持背压。 从 BackpressureStrategy 的源码可以看到,Flowable 一共有 5 中背压策略。
- MISSING 此策略表示通过 create 方法创建的 Flowable 没有指定背压策略,不会对通过 OnNext 发射的数据做缓存或丢弃处理,需要下游通过背压操作符(onBackpressureBuffer()/onBackpressureDrop()/onBackpressureLatest())指定背压策略。
- ERROR 此策略表示如果放入 Flowable 的异步缓存池中的数据超限了,则会抛出 MissingBackpressureException 异常。
- BUFFER 此策略表示 Flowable 的异步缓存池同 Observable 的一样,没有固定大小,可以无限制添加数据,不会抛出 MissingBackpressureException 异常,但会导致 OOM(Out of Memory)。
- DROP 此策略表示如果 Flowable 的异步缓存池满了,就会丢掉将要放入缓存池中的数据。
- LATEST 此策略表示,如果缓存池满了,会丢掉将要放入缓存池中的数据。这一点与 DROP 策略一样,不同的是,不管缓存池的状态如何,LATEST 策略会将最后一条数据强行放入缓存池中。