RxJava小試牛刀

好久沒有寫技術(shù)文章了吗货,工作上了解到RxJava框架適合我們的某些業(yè)務(wù)場景维雇,所以嘗試著RxJava整合到我們的業(yè)務(wù)代碼肥橙,以解決部分問題栽燕。

很粗糙很狂野的整合進(jìn)來暂氯,沒有細(xì)致的琢磨框架潮模,以觀察者模式實現(xiàn)的框架配合以鏈?zhǔn)秸{(diào)用的代碼風(fēng)格,看起來確實稍微‘高大上’一些痴施。

業(yè)務(wù)場景

當(dāng)下主流的微服務(wù)架構(gòu)體系中擎厢,各個微服務(wù)的業(yè)務(wù)之間相互獨立,比如商品晾剖、訂單锉矢、客戶等等,它們即可獨立提供服務(wù)齿尽,也可與其他服務(wù)協(xié)同沽损,于是便涉及到業(yè)務(wù)聚合,比如前端展示一個商品詳情頁會涉及到商品信息循头,價格绵估,評價等等的數(shù)據(jù)炎疆,如下。

image.png

比如用戶進(jìn)入商品詳情頁国裳,可能會發(fā)生什么形入?用戶需要看到商品的詳細(xì)信息,包括價格缝左,屬性等等亿遂,同時還需要看到優(yōu)惠券信息、以及相關(guān)的評價渺杉。(這里是假設(shè)一個請求需要處理這么多事)

image.png
// 偽代碼如下
GoodsBean goodsBean = goodsFeignService.queryGoods();
List<CouponBean> couponBeans = couponFeignService.queryCoupon();
List<EvaluationBean> evaluations = evaluationFeignService.queryEvaluation();
 // 真實的業(yè)務(wù)場景往往更加復(fù)雜
return join.map(goodsBean, couponBeans, evaluations);

這么寫毫無疑問也是可以把業(yè)務(wù)跑起來蛇数,但是作為一名優(yōu)秀的互聯(lián)網(wǎng)底層搬磚工作者,除了完成必要的工作是越,盡可能希望把代碼寫的優(yōu)雅一些耳舅,就像砌墻的時候砌地更光滑,同時還能稍微提高一些性能倚评?

解決方案

RxJava可以很好地解決該業(yè)務(wù)訴求浦徊,利用異步并發(fā)提升一點性能,將應(yīng)用中的無依賴操作轉(zhuǎn)為異步并發(fā)處理天梧。無依賴(或已完成依賴)操作比如:

  • 數(shù)據(jù)庫讀取
  • feign遠(yuǎn)程RPC調(diào)用
  • 第三方開放平臺接口調(diào)用
  • ……

public abstract class AbstractObserver implements Observer<JoinQueryParameter> {

    /**
     * 日志
     */
    public final static Logger logger = LoggerFactory.getLogger(AbstractObserver.class);

    private ResultMap resultMap;
    private JoinQueryParameter joinQueryParameter;

    @Override
    public void onSubscribe(Disposable disposable) {}

    @Override
    public void onNext(JoinQueryParameter joinQueryParameter) {
        resultMap = this.queryOriginalData(joinQueryParameter);
        update(joinQueryParameter);
    }

    @Override
    public void onError(Throwable throwable) {
        logger.error("查詢信息發(fā)生異常", throwable);
    }

    @Override
    public void onComplete() {
        this.onCompleteEvent(joinQueryParameter, resultMap);
    }

    /**
     * 查詢初始化信息
     * @param JoinQueryParameter 
     * @return
     */
    protected abstract ResultMap queryOriginalData(JoinQueryParameter joinQueryParameter);

    /**
     * 加載數(shù)據(jù)完成后的事件
     *
     * @param JoinQueryParameter 
     * @param resultMap
     */
    protected abstract void onCompleteEvent(JoinQueryParameter joinQueryParameter, ResultMap  resultMap);
}


public abstract class AbstractObservableStrategy extends AbstractObserver {

    /**
     *
     * @param joinQueryParameter
     * @return
     */
    public AbstractObservableStrategy create(final JoinQueryParameter joinQueryParameter) {
        Observable.create(new ObservableOnSubscribe<JoinQueryParameter>(){

            @Override
            public void subscribe(ObservableEmitter<JoinQueryParameter> e) throws Exception {
                e.onNext(joinQueryParameter);
                e.onComplete();
            }

        }).subscribe(this);
        return this;
    }

    /**
     * 查詢初始化依賴數(shù)據(jù)
     * @param joinQueryParameter
     * @return
     */
    protected abstract ResultMap queryOriginalData(JoinQueryParameter joinQueryParameter);

    /**
     * 加載數(shù)據(jù)完成后的事件
     *
     * @param joinQueryParameter
     * @param resultMap
     */
    protected abstract void onCompleteEvent(JoinQueryParameter joinQueryParameter, ResultMap resultMap);

    /**
     * 增加聚合查詢方法
     *
     * @param joinQueryParameter
     * @param iQueryData
     * @return
     */
    protected Observable addObservable(JoinQueryParameter joinQueryParameter, final IQueryData iQueryData) {
        return Observable.just(joinQueryParameter)
                .flatMap(new Function<JoinQueryParameter, ObservableSource<ResultMap>>() {

                    @Override
                    public ObservableSource apply(JoinQueryParameter joinQueryParameter) throws Exception {
                        return Observable.just(iQueryData.queryData(joinQueryParameter));
                    }
                }).subscribeOn(Schedulers.io())
              ;
    }
}

public interface IQueryData {


    /**
     * 查詢列表
     * @param joinQueryParameter
     * @return
     */
    ResultMap queryData(JoinQueryParameter joinQueryParameter);
}


public class DefaultObservbleStrategy extends AbstractObservableStrategy {

    /**
     * 日志
     */
    public final static Logger logger = LoggerFactory.getLogger(DefaultObservbleStrategy.class);

    /**
     * 查詢初始化信息
     * @param joinQueryParameter
     * @return
     */
    @Override
    protected ResultMap queryOriginalData(JoinQueryParameter joinQueryParameter) {
        return new GoodsQueryDataImpl().queryData(joinQueryParameter);
    }

    /**
     * 加載數(shù)據(jù)完成后的事件
     *
     * @param joinQueryParameter
     * @param originalData
     */
    @Override
    protected void onCompleteEvent(JoinQueryParameter joinQueryParameter, ResultMap originalData) {
        ResultMap resultMap = (ResultMap)Observable.zip(
                Observable.just(originalData),
                addObservable(joinQueryParameter, new QueryCouponImpl()),
                addObservable(joinQueryParameter, new QueryEvaluationImpl()),
                new Function5<ResultMap, ResultMap, ResultMap, ResultMap, ResultMap, ResultMap>() {

                    @Override
                    public ResultMap apply(ResultMap goodsMap, ResultMap couponMap, ResultMap couponEvaluation) throws Exception {
                        return join.map(goodsMap, couponMap, couponEvaluation);
                    }

                }
        ).blockingLast();
        DefaultObservbleStrategy.this.setResultMap(resultMap);
    }
}

以上是實現(xiàn)時寫的大致骨架盔性,由于具體業(yè)務(wù)遠(yuǎn)遠(yuǎn)比此文列舉的需求要復(fù)雜,故而整的略微復(fù)雜了呢岗,但是找到關(guān)鍵的節(jié)點代碼即可纯出。

Observable.zip(
                Observable.just(joinQueryParameter)
                .flatMap(new Function<JoinQueryParameter, ObservableSource<ResultMap>>() {

                    @Override
                    public ObservableSource apply(JoinQueryParameter joinQueryParameter) throws Exception {
                        return Observable.just(iQueryData.queryData(joinQueryParameter));
                    }
                }).subscribeOn(Schedulers.io()),
                 Observable.just(joinQueryParameter)
                .flatMap(new Function<JoinQueryParameter, ObservableSource<ResultMap>>() {

                    @Override
                    public ObservableSource apply(JoinQueryParameter joinQueryParameter) throws Exception {
                        return Observable.just(iQueryData.queryData(joinQueryParameter));
                    }
                }).subscribeOn(Schedulers.io())敷燎,
                new Function<ResultMap, ResultMap, ResultMap>() {

                    @Override
                    public ResultMap apply(ResultMap goodsMap, ResultMap couponMap, ResultMap couponEvaluation) throws Exception {
                        return join.map(goodsMap, couponMap, couponEvaluation);
                    }

                }
        ).blockingLast();

總而言之,微服務(wù)盛行后箩言,服務(wù)與服務(wù)之間的數(shù)據(jù)聚合愈發(fā)復(fù)雜硬贯,讓人有點頭疼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陨收,一起剝皮案震驚了整個濱河市饭豹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌务漩,老刑警劉巖拄衰,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饵骨,居然都是意外死亡翘悉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門居触,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妖混,“玉大人老赤,你說我怎么就攤上這事≈剖校” “怎么了抬旺?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祥楣。 經(jīng)常有香客問我开财,道長,這世上最難降的妖魔是什么误褪? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任责鳍,我火速辦了婚禮,結(jié)果婚禮上振坚,老公的妹妹穿的比我還像新娘薇搁。我一直安慰自己,他們只是感情好渡八,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布啃洋。 她就那樣靜靜地躺著,像睡著了一般屎鳍。 火紅的嫁衣襯著肌膚如雪宏娄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天逮壁,我揣著相機與錄音孵坚,去河邊找鬼。 笑死窥淆,一個胖子當(dāng)著我的面吹牛卖宠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忧饭,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼扛伍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了词裤?” 一聲冷哼從身側(cè)響起刺洒,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吼砂,沒想到半個月后逆航,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡渔肩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年因俐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡女揭,死狀恐怖蚤假,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吧兔,我是刑警寧澤磷仰,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站境蔼,受9級特大地震影響灶平,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜箍土,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一逢享、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吴藻,春花似錦瞒爬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至航罗,卻和暖如春禀横,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粥血。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工柏锄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人复亏。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓趾娃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缔御。 傳聞我的和親對象是個殘疾皇子茫舶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容