RxJava retryWhen 异常业务处理总结

本文介绍了如何通过研究`retryWhen`操作符的源码,利用静态代理和装饰模式封装异常,以便在异常中添加业务信息,实现在异常处理中的线上问题排查。作者详细展示了异常类的创建、异常处理函数的实现以及业务代码如何应用这些技术。
摘要由CSDN通过智能技术生成

背景

在实际业务中,交易都是由多个上游组成的,一般成功的数据组织能够满足我们设计的要求,但是如果其中某个环节出了异常,在最终的下游很难捕获到哪里出了错误,尤其是需要在异常中添加一些业务信息与埋点功能相合作,完成线上问题排查,特此通过研究retryWhen操作符号源码,通代理模式,将异常进行统一封装处理,已满足这个场景的要求。

异常源码

// 封装一个业务需要的异常类,采用静态代理(装饰模式)扩展原异常
class BizThrowableExt(cause: Throwable?): Throwable(cause) {
  	// 业务相关数据,也可以通过继承,组合等模式形成复杂的业务属性
    var url:String = ""
    var code:String = ""
    var msg:String = ""
}

异常处理源码

异常处理源码,实现Function,在内部通过flatMap操作,对上游传递下来的异常进行封装处理,最后通过 Observable.error 将异常再往下游传递。

import io.reactivex.Observable
import io.reactivex.ObservableSource
import io.reactivex.functions.Function
class ThrowableTransform<R>(private val url:String, private var code:String="", private var msg:String=""):Function<Observable<Throwable>,ObservableSource<R>> {
    override fun apply(attempts: Observable<Throwable>): ObservableSource<R> {
        return attempts.flatMap {
            Observable.error(transform(it,url, code, msg))
        }
    }

    private fun transform(original:Throwable, url:String, code:String, msg:String):Throwable{
        return BizThrowableExt(original).apply {
            this.url = url
            this.msg = msg
            this.code = code
        }
    }

}

业务源码

业务源码通模式登录和获取token 相关业务,在发生异常时,将业务相关信息,传递到下游,下游可以根据异常,获取到业务信息,和原始的异常。

    private fun test2(){
        Observable.zip(observableLogin(),observableToken()) { userInfo, token ->
            println(" userInfo== $userInfo,token == $token")
            userInfo + token
        }.observeOn(AndroidSchedulers.mainThread())
            .subscribe ({
                println("${Thread.currentThread().id} resutl == $it")
        },{
            if(it is BizThrowableExt){
                println("url == ${it.url}")
            }
            })
    }
    // 模拟登录相关业务
    private fun observableLogin(): Observable<String?> {
        return Observable.create(ObservableOnSubscribe<String?> { e: ObservableEmitter<String?> ->
            println("observableLogin thread id ${Thread.currentThread().id}")
            Thread.sleep(3000)
            e.onNext("user login")
            e.onError(RuntimeException())
            e.onComplete()
        }).subscribeOn(Schedulers.io())
            .retryWhen(ThrowableTransform<String>("loginUrl","登录相关错误","登录相关信息"))
    }

    private fun observableToken(): Observable<String?> {
        val data1 = "发起token其他信息"
        return Observable.create(ObservableOnSubscribe<String?> { e: ObservableEmitter<String?> ->
            try{
                println("observableToken thread id ${Thread.currentThread().id}")
                Thread.sleep(5000)
                e.onNext("user token")
                e.onComplete()
            }catch (e:Exception){
                //throw  e
            }
        }).subscribeOn(Schedulers.io())
            .retryWhen(ThrowableTransform<String>("tokeUrl","token相关错误",data1))
    }

实现原理

名称定义:

  1. 通过代码Observable.create 创建的 Observable 称为 原上游 Observable
  2. retryWhen 内部创建的 Observable 称为异常处理上游
  3. 通过 subscribe 创建的Observer称为原下游
    调用源码
Observable.create { e: ObservableEmitter<String?> ->
            e.onNext("A")
            e.onComplete()
        }.retryWhen { attempts->
            var count = 0;
            attempts.flatMap { throwable ->
                if(count < 3){
                    Observable.just("just retry!")
                }else{
                    Observable.error(throwable)
                }

            }
        }.subscribe {
            println("result $it")
        }

调用入口

public final Observable<T> retryWhen(
            final Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler) {
        ObjectHelper.requireNonNull(handler, "handler is null");
        // 将retryWhen的上游(例子中是用Observable.create 创建出的上游)和 处理异常构建的上游 通过 ObservableRetryWhen 返回一个新的上游,带异常处理的上游
        // 可以简单的认为 在参数1 中 添加了一个参数2 的功能
        return RxJavaPlugins.onAssembly(new ObservableRetryWhen<T>(this, handler));
    }

实现原理即rertyWhen源码

public final class ObservableRetryWhen<T> extends AbstractObservableWithUpstream<T, T>{
	final Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler;
	public ObservableRetryWhen(ObservableSource<T> source, Function<? super Observable<Throwable>, ? extends ObservableSource<?>> handler) {
		// 保存原上游
        super(source);
        this.handler = handler;
    }

    @Override
    protected void subscribeActual(Observer<? super T> observer) {
    	// 构建一个新的Subject ,接受订阅后的异常
        Subject<Throwable> signaller = PublishSubject.<Throwable>create().toSerialized();

        ObservableSource<?> other;

        try {
            other = ObjectHelper.requireNonNull(handler.apply(signaller), "The handler returned a null ObservableSource");
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            EmptyDisposable.error(ex, observer);
            return;
        }
		// 将上游和下游,和异常处理器封装起来
		// 注意 RepeatWhenObserver 也是 Observer
		//  RepeatWhenObserver 在 订阅关系发生时,是先调用到RepeatWhenObserver
		//  RepeatWhenObserver 根据接受到的数据,在合适的机会给下游传递
        RepeatWhenObserver<T> parent = new RepeatWhenObserver<T>(observer, signaller, source);
        observer.onSubscribe(parent);
		// other(内部有signaller) 和 parent.inner 形成订阅关系
        other.subscribe(parent.inner);
		// 将原上游和RepeatWhenObserver 形成订阅关系
        parent.subscribeNext();
    }
}

RepeatWhenObserver 源码如下

 static final class RepeatWhenObserver<T> extends AtomicInteger implements Observer<T>, Disposable {

        private static final long serialVersionUID = 802743776666017014L;

        final Observer<? super T> downstream;

        final AtomicInteger wip;

        final AtomicThrowable error;

        final Subject<Throwable> signaller;

        final InnerRepeatObserver inner;

        final AtomicReference<Disposable> upstream;

        final ObservableSource<T> source;

        volatile boolean active;

        RepeatWhenObserver(Observer<? super T> actual, Subject<Throwable> signaller, ObservableSource<T> source) {
            this.downstream = actual;
            this.signaller = signaller;
            this.source = source;
            this.wip = new AtomicInteger();
            this.error = new AtomicThrowable();
            this.inner = new InnerRepeatObserver();
            this.upstream = new AtomicReference<Disposable>();
        }

        @Override
        public void onSubscribe(Disposable d) {
        		// 将原下游替换为 RepeatWhenObserver
            DisposableHelper.replace(this.upstream, d);
        }

        @Override
        public void onNext(T t) {
        	// 调用原下游继续传递onNext事件
            HalfSerializer.onNext(downstream, t, this, error);
        }

        @Override
        public void onError(Throwable e) {
            DisposableHelper.replace(upstream, null);
            active = false;
            // 通过 signaller 转到 inner 中处理,将throwable 事件转换为 onNext事件
            signaller.onNext(e);
        }

        @Override
        public void onComplete() {
        	// 取消相关处理,包括 inner
            DisposableHelper.dispose(inner);
            // 调用原下游downstream 的onComplete
            HalfSerializer.onComplete(downstream, this, error);
        }

        @Override
        public boolean isDisposed() {
            return DisposableHelper.isDisposed(upstream.get());
        }

        @Override
        public void dispose() {
            DisposableHelper.dispose(upstream);
            DisposableHelper.dispose(inner);
        }

        void innerNext() {
        	// 重新将原上游和 RepeatWhenObserver 形成订阅关系
            subscribeNext();
        }

        void innerError(Throwable ex) {
            DisposableHelper.dispose(upstream);
            // 直接调用原上游的onError 
            HalfSerializer.onError(downstream, ex, this, error);
        }

        void innerComplete() {
            DisposableHelper.dispose(upstream);
            HalfSerializer.onComplete(downstream, this, error);
        }

        void subscribeNext() {
            if (wip.getAndIncrement() == 0) {

                do {
                    if (isDisposed()) {
                        return;
                    }

                    if (!active) {
                        active = true;
                        source.subscribe(this);
                    }
                } while (wip.decrementAndGet() != 0);
            }
        }
	 // 当原上游 出现异常时候,在 InnerRepeatObserver 处理
        final class InnerRepeatObserver extends AtomicReference<Disposable> implements Observer<Object> {

            private static final long serialVersionUID = 3254781284376480842L;

            @Override
            public void onSubscribe(Disposable d) {
                DisposableHelper.setOnce(this, d);
            }

            @Override
            public void onNext(Object t) {
                innerNext();
            }

            @Override
            public void onError(Throwable e) {
                innerError(e);
            }

            @Override
            public void onComplete() {
                innerComplete();
            }
        }
    }

总结

  1. retryWhen 是将 原下游封装为RepeatWhenObserver
  2. 当上游数据订阅时,替换为 RepeatWhenObserver的dispose
  3. 原上游 onNext onComplete 通过 RepeatWhenObserver 调用原下游的onNext onComplete
  4. 将retryWhen 入参 ,和 RepeatWhenObserver 的 InnerRepeatObserver 形成订阅关系
  5. 在原上游 发生onError时,调用到 retryWhen 的入参构建的上游
  6. 在 retryWhen 的入参构建的上游 调用onNext 是,通过subscribeNext(); 将订阅关系重置,当调用onError 时,直接向下游传递 onError。
  7. 根据第6点,文章对原上游的异常进行封装不会更改原数据的传递,并且可以将封装后的异常传递到下游。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值