RxJava在業務系統中的實踐

在java的世界裏由於大多數接口和API都是阻塞式的交互,進而影響到很多童靴的編程思想和編程習慣。因而,有一些專家講java的編程模型是阻塞式模型(與Node.js區別大),不是沒有道理的。從高性能的視角看,任何阻塞點都可能導致性能的退步。而響應式編程其天然就是非阻塞的,當數據準備完成後自動觸發下一個動作而不是等待數據完成。這種思想再結合異步化編程使得我們在統一線程模型,降低多線程編程成本的同時提升整個系統的吞吐量。

劃重點

異步化編程不同於傳統的阻塞式編程,在任務處理上異步化編程的關注點已發生轉移:

以前一個線程中執行完所有的computation任務和IO任務>>>>>>如今需要computation任務和IO任務分離進行處理(CPU只關注computation任務)

響應式架構

由業務組件構成,業務組件由事件異步驅動

那如何結合業務進行優化呢?

首先要找出業務系統中的阻塞點,進行分類,各個擊破。

應用日誌

日誌的性能顯得很重要,雖然log4j和logback都提供了異步方式,但是它們本質上還是基於鎖來實現。log4j2是新一代的基於LMAX Disruptor的無鎖異步日誌系統,在多線程程序中,其吞吐量比log4j和logback高10倍左右。

HTTP請求

服務端異步其實之前也講過,瞭解spring mvc的異步特性介紹

RPC調用

客戶端異步改造其實不難

其實應用日誌、HTTP請求、RPC調用...等改造起來不難,最麻煩最有挑戰性的是執行範式上(串行請求)的改造。

實踐1:根據訂單號需查詢:商品信息、商品詳情(需要更新緩存)、瀏覽量、留言信息

感受下,是不是感覺世界美好了很多!

//根據訂單號查訂單
Flowable<Order> orderFlow = Flowable.fromCallable(() -> queryOrder(orderId));
//查商品
Flowable<Item> itemFlow = orderFlow.flatMap(order -> Flowable.fromCallable(() -> queryItem(order.getId())));
//查詢商品相關信息
Flowable<Detail> detailFlow = itemFlow.flatMap(item -> {
   //瀏覽量
   Flowable<Long> pvFlow = Flowable.fromCallable(() -> queryItemPv(item.getId()));
   //留言
   Flowable<Comment> commentFlow = Flowable.fromCallable(() -> queryItemComment(item.getId()));
   //瀏覽,留言,商品共同組成detail
   return Flowable.zip(pvFlow,commentFlow,(pv,comment) -> buildItemDetail(item,pv,comment));
});
//更新緩存(doOnNext不會對流的結果造成任何影響,只是觸發一個操作)
detailFlow.doOnNext(detail -> cache(detail));

實踐2:支付

Response response=Observable.zip(
    callAsync(()->updateStock()),
    callAsync(()->updatPayHistroy()),
    callAsync(()->updateOrder()),
    (response1,response2,response3)-> response()
).blockingGet();

目前響應式純異步編程在業務系統的應用仍然處於起步階段,暫時沒法完全消除阻塞點,改造的過程中需要重點關注:

  • 業務組件的抽象及依賴上治理
  • cpu核數個線程來調度所有的computation任務
  • 底層的IO線程模型統一(RPC,HTTP,緩存都是各自維護自己的線程池),理論上這些線程池都可以趨於統一
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章