官术网_书友最值得收藏!

1.4 響應式開發工具庫

已經有很多工具庫實現了響應式流的標準,包括Akka、Reactor、RxJava、Streams、Vert.x等。下面簡單介紹幾種,在后面的章節中我會重點講解RxJava(關于Reactor,會在本系列叢書的另一本書中具體講解)。

1.4.1 RxJava簡介

通過官方GitHub可知,RxJava是使用Java語言開發的專門針對JVM的一種響應式擴展工具,通過它可以輕松地在服務器端實現并發操作。RxJava的目的就是處理客戶端越來越復雜的請求,在服務器端通過并行計算快速地響應請求。

接下來,我們開始了解RxJava到底是怎么一回事,作為數據的消費者,我們會對獲得的數據做出各種反應。有句話說得好,“跳出三界外,不在五行中”,在我們以旁觀者的視角來看這件事的時候,其實它就是一個觀察者模式的實際體現。RxJava下的響應式編程其實就是基于影院里的電影(Observable)提供的內容(生產者數據)傳播給訂閱者,然后訂閱者做出相應的反應。

結合上面的場景,下面對RxJava所涉及的要點進行解釋。

● Observable:表示數據源,Observable會發出一定數量的元素,發送可能會成功,也可能在這個過程中出現狀況而失敗。從電影院的場景可以知道,同一時間Observable可以有多個訂閱者。

● Observer或Subscriber:表示訂閱者,通過監聽Observable來消費Observable所發送的元素。

● Methods:表示一系列操作API,對下發數據進行加工整合。

● onNext:在一個元素被Observable發送出去的時候,通過該方法可以調用每一個訂閱者。

● onComplete:在Observable成功發送完所有數據后,會調用這個方法來收尾。

● onError:當Observable發送數據的過程中出現錯誤的狀況時,會調用這個方法結束發送并返回一個error事件。

RxJava所帶來的好處主要如下。

● 允許我們進行一系列的異步操作。

● 有時為了跟蹤狀態,我們會通過一個原子類變量保存之前計算的值。我們無須專門使用原子類來跟蹤狀態,因為RxJava中已經封裝了這些操作。

● RxJava提供了一個在整個執行過程中發生錯誤時的處理途徑。

1.4.2 Reactor簡介

Spring 5官方文檔提到,其通過Reactor的支持,在服務器端獲得了更高的性能和更快的響應速度。Spring WebFlux作為新一代的Web開發框架,以Reactor作為基礎框架進行異步編程的開發,從而可以使我們寫出性能更好的Web應用程序。如果大家看過我博客中關于Spring 5源碼分析的系列文章,就可以知道Spring MVC框架的整個運行過程其實使用了事件驅動(Event-Driven)模式,而Reactor自身的設計也使用了這個模式。參考前面的電影院場景,當電影的畫面和聲音傳到你的眼睛和耳朵中時,會引發你喜怒哀樂的情緒反應。再形象一點,在拳擊選手一個直拳要打到對方選手臉上的時候,對方選手會躲閃。電影的畫面和拳擊選手的直拳動作都是一種事件的表現,根據事件做出相應處理的整個過程就是所謂的事件驅動。在Spring里,這就相當于我們的后臺服務器接收事件請求,通過multicaster多路分發器來分發給相應的監聽器(Listener),最后由監聽器里定義的相應的handler來做具體處理。整個過程大概就是這樣的。

知道了上面的這些內容,通過使用Reactor,我們寫出的程序就可以按照事件驅動的模式很輕易地異步運行了。

1. Reactor的優點

Reactor支持完全無阻塞,其主要的目標之一就是解決傳統Web開發方案對于異步支持的各種弊病。它提供了十分有效的途徑來支持背壓。它還有以下優點。

● 豐富的API,可以對數據流進行操作。

● 提供了一種可讀性更強的代碼書寫方式,使我們所寫的代碼可以更方便地得到維護。

● 與流相同,無消費,不執行。

● 消費者具備發信號通知生產者元素按需下發的能力(RxJava同樣具備)。

2. Reactor的核心功能

Reactor項目的主要模塊是reactor-core,這是一個專門用于支持響應式流規范的類庫,其支持Java 8及后續版本。通過查看Reactor API,可知它和RxJava很像。Reactor 3是Reactor 2和RxJava的核心貢獻開發者一起完成的一個混合版本,這也是本章把這幾個東西放在一起介紹,然后分章講解的很重要的原因,因為這樣更易于理解。

Reactor與RxJava有相同的Publisher、Subscriber、Subscription和Processor核心接口。這里只簡單介紹Publisher最常用的兩個實現Mono和Flux,以及相關的操作符。

● Mono:表示一個特殊的Publisher,它可以發送0個或1個元素。

● Flux:表示一個特殊的Publisher,它可以發送0到n個元素。

● 操作符:元素在從Publisher發送給訂閱者之前,可能會需要進行一些處理,包括轉換、過濾操作等。

1.4.3 MongoDB簡介

在后面的實戰開發中,我們可能會用到MongoDB,官方提供的MongoDB Reactive Streams Java版本的驅動包API可以對MongoDB進行異步流處理,而且是無阻塞支持背壓的。這里只是提一下,說明我們的數據庫操作層面也開始做到了對響應式流API標準的支持。

1.4.4 響應式項目用例

前面說了那么多,大家可能依然有點不明白,那么為了更好地理解響應式系統(Reactive System),我們看看它與傳統項目的不同之處。

以我們生活中的股票場景為例,我們需要看到股票信息的實時動態展示。這時我們會打開并保持一個頁面,這個頁面可以實時顯示股票信息。開發人員需要做的是,將最新的數據更新到這個股票展示頁面上。作為股民,面對的是“差之毫厘,失之千里”的局面。對他們來說,數據刷新得越及時,對決策越有利(在這里,我們只從響應式的角度來考慮這個問題,現實項目中會有基于WebSocket的實現,Spring MVC中也有SSE的實現)。

1. 傳統開發模式

根據以往的開發經驗,我們會主動地檢查股票價格有沒有變化,如果有變化,就從后臺拉取最新的數據。如圖1-1所示的流程圖就代表著傳統開發模式。

圖1-1

在傳統開發模式下,一旦開始渲染訪問頁面,就會每隔一段時間(圖1-1中是1分鐘)發送AJAX請求到后臺的查詢服務去請求股票價格數據。使用這種方式,無論股票價格是否真的發生變化,都會去請求,但無法保證股票價格的變化會被立刻傳遞到Web頁面上。

2. 響應式開發模式

響應式開發模式通過事件驅動的方式將各個組件連接到一起,以實現在事件發生時其他組件可以立即進行響應。

也就是說,在加載股票價格頁面后,這個頁面會有一個專屬ID注冊到股票查詢服務上。一旦使股票價格發生變化的事件產生,這個事件(Event)就會觸發響應,最新的股票價格就會在Web頁面上進行更新顯示。如圖1-2所示說明了整個流程。

圖1-2

可以看到,響應式開發模式一般包括下面3個步驟。

(1)訂閱(Subscribing)事件。

(2)事件的發生與傳播。

(3)解除訂閱。

在股票價格頁面初始化加載的時候,其中有一個動作就是訂閱當前使股票價格發生變化的事件源,可以認為事件源是消息中間件里的主題(Topic)(或者是我們訂閱的一個RSS主題),而不同的響應式框架會有不同的具體方式,使用消息中間件也可以實現訂閱。

在我們所關注的某只股票價格發生變化的時候,一個新的事件就會產生并分發給這個事件的訂閱者。我們的Web頁面會及時地接收并更新股票價格數據。而一旦Web頁面關閉或者刷新,一個解除訂閱的請求就會被發送至后臺。

3. 傳統開發模式和響應式開發模式的比較

可以看到,傳統開發模式是比較簡單的,而響應式開發模式需要我們實現一個訂閱和事件傳播鏈。如果事件的傳播需要跨項目,也就是涉及其他項目,那么就可能會使用到消息中間件,這將會變得復雜,其并不屬于本書的范圍,此處不做討論。

在傳統開發模式中,更新股票價格頁面主要是基于盲目的主動拉取來實現的,前端根本就不知道會不會有數據發生變化。這也就意味著無論后臺數據有沒有發生變化,前端都需要定時從后臺拉取一次數據。而在響應式開發模式中,一旦注冊訂閱了價格變動事件,那么只有這只股票的價格發生變化才會觸發一系列的操作,這樣明顯提高了程序性能和用戶體驗。

在傳統開發模式中,這個例子中線程的生命周期會比較長,這也就意味著該線程所使用的資源在這個過程中會被線程鎖定。考慮到同一時刻服務器會接收大量的請求,這樣勢必會造成更多的線程相互爭奪資源。在響應式開發模式中,線程生存的時間短,這也就意味著爭奪資源的情況較少,后面在本書中會針對類似場景進行相應的實戰Demo展示。

主站蜘蛛池模板: 伊春市| 靖远县| 温泉县| 弥勒县| 镇坪县| 平舆县| 丰镇市| 仙居县| 荆州市| 尼木县| 独山县| 瑞金市| 闵行区| 永顺县| 康马县| 临汾市| 诸暨市| 吉木乃县| 万全县| 清流县| 定兴县| 宿迁市| 温泉县| 金堂县| 宜宾县| 遂川县| 霍州市| 安仁县| 扶绥县| 翁牛特旗| 台东市| 大英县| 厦门市| 秭归县| 当涂县| 昌江| 连南| 宁强县| 临澧县| 诸暨市| 林周县|