原文連接:
《Java編程方法論:響應式RxJava與代碼設計實戰》序,來自於微信公衆號:
次靈均閣
在《2019 一月的InfoQ 架構和設計趨勢報告》1中,響應式編程(Reactive Programming)和函數式(Functional Programing)仍舊編列在第一季度(Q1)的 Early Adopters(早期採納者) 中。儘管這僅是一家之言,然而很多的開發人員逐漸意識到 Reactive 之風儼然吹起。也許您的生產系統還沒有出現 Reactive 的身影,不過您可能據說過 Spring WebFlux 或 Netflix Hystrix 等開源框架。筆者曾請教過 Pivotal(Spring 母公司)佈道師 Josh Long2:」Spring 技術棧將來的重心是否要佈局在 Reactive 之上?「。對方的答覆是:」沒錯,Reactive 是將來趨勢。「。同時,愈來愈多的開源項目開始簽署 Reactive 宣言(The Reactive Manifesto)3,並喊出 」Web Are Reactive「 的口號。html
或許開源界的種種舉動沒法說服您向 Reactive 的」港灣「中停靠,不過 Java 9 Flow API4 的引入,又給業界注入了一劑強心針。不難看出,不管是 Java API,仍是 Java 框架均走向了 Reactive 編程模型的道路,這並不是是一種巧合。java
一般,人們談到的 Reactive 可與 Reactive 編程劃上等號,以」非阻塞(Non-Blocking)「和」異步(Asynchronous)「的特性並述,數據結構與操做相輔相成。Reactive 涉及函數式和併發兩種編程模型,前者關注語法特性,後者強調執行效率。簡言之,Reactive 編程的意圖在於 」Less Code,More Efficient「。除此以外,我的認爲 Reactive 更大的價值在於統一 Java 併發編程模型,使得同步和異步的實現代碼無異,同時作到 Java 編程風格與其餘編程語言更好地融合,或許您也發現 Java 與 JS 在 Reactive 方面並不存在本質區別。縱觀 Java 在 Reactive 編程上的發展而看,其特性更新可謂是步步爲營,如履薄冰。儘管 Java 線程 API Thread
與 Runnable
就已具有異步以及非阻塞的能力,然而同步和異步編程的模式並不統一,而且理解 Thread
API 的細節和管理線程生命週期的成本均由開發人員歸納承受。雖然 Java 5 引入 J.U.C 框架(Java 併發框架)以後, ExecutorService
實現減輕了以上負擔。不過開發人員仍需關注 ExecutorService
實現細節,好比怎樣合理地設置線程池空間以及阻塞隊列又成爲新的挑戰。爲此,Java 7 又引入 ForkJoinPool
API,不過此時的J.U.C 框架與 Reactive 理念仍存在距離,即便是線程安全的數據結構,也並不具有並行計算的能力,如:集合並行排序,同時操做集合的手段也至關的貧瘠,缺乏相似 Map/Reduce 等操做。不過這些困難只是暫時的,終究被 Java 8 」救贖「。Stream
API 的出現不但具有數據操做在串行和並行間自由切換的能力,如 sequential()
以及 parallel()
方法,並且淡化了併發的特性,如 sorted()
方法便可能是傳統排序,亦或是並行排序。相同的設計哲學也體如今 Java Reactive 實現框架中,如同書中說起的 RxJava5 API io.reactivex.Observable
。統一編程模型只是 Stream
其中設計目標之一,它結合 Lambda 語法特性,雖然提供了數量可觀的操做方法,如 flatMap()
等,然而不管對比 RxJava,仍是 Reactor6 ,Stream
操做方法卻又相形見絀。值得一提的是,這些操做方法在 Reactive 的術語中稱之爲操做符(Operators)。固然框架內建的操做符的多與寡,並不是判斷其是否爲 Reactive 實現的依據。其中決定性因素在於數據必須來源於發佈方(生產者)的」推送(Push)「,而非消費端的」拉取(Pull)「。顯然,Stream
屬於消費端已就緒(Ready)的數據集合,並不存在其餘數據推送源。不過 JVM 語言早期的 Reactive 定義處於模糊地帶,如 RxJava API 屬於觀察者模式(Observer Pattern)7的擴展,而非迭代器(Iterator Pattern)模式8的實現。而 Reactor 的實現則擁抱 Reactive Streams 規範9 ,該規範消費端對於數據的操做是被動的處理,而非主動的索。換言之,數據的到達存在着不肯定性10。當推送的數據沒法獲得消費端及時效應時,Reactive 框架必須提供背壓(Backpressure)11實現,確保消費端擁有」拒絕的權利(cancel)」。在此理論基礎上,Reactive Streams 規範定義了一套抽象的 API,做爲 Java 9 java.util.concurrent.Flow
API 的頂層設計。不過關於操做符的部分,該規範彷佛不太關心,這也是爲何 RxJava 和 Reactor 均稱自身爲 Reactive 擴展框架的緣由,同時二者在 API 級別提供多種調度器(Schedulers)12實現,適配不一樣併發場景提供。儘管 Reactive 定義在不一樣的陣營之間存在差別,援引本人在《Reactive-Programming-一種技術-各自表述》13文中的總結:react
Reactive Programming 做爲觀察者模式( Observer) 的延伸,不一樣於傳統的命令編程方式( Imperative programming)同步拉取數據的方式,如迭代器模式( Iterator) 。而是採用數據發佈者同步或異步地推送到數據流(Data Streams)的方案。當該數據流(Data Steams)訂閱者監聽到傳播變化時,當即做出響應動做。在實現層面上,Reactive Programming 可結合函數式編程簡化面嚮對象語言語法的臃腫性,屏蔽併發實現的複雜細節,提供數據流的有序操做,從而達到提高代碼的可讀性,以及減小 Bugs 出現的目的。同時,Reactive Programming 結合背壓(Backpressure)的技術解決發佈端生成數據的速率高於訂閱端消費的問題。
不難看出,Reactive 是一門綜合的編程藝術,在實現框架的加持下,相同的代碼邏輯實現同步和異步非阻塞功能,從而達到提高應用總體性能的目的。不過現實的狀況或許沒有那麼理想,Spring 官方文檔在《Web on Reactive Stack》章節中提到,"Reactive 和非阻塞一般並非讓應用運行的更快"14:git
Reactive and non-blocking generally do not make applications run faster.
爲此,JHipster15 給出了一份《 Spring 5 WebFlux 性能測試報告》16,其中一條結論是,」Reactive 應用並無表現出速度提高(甚至是變得更差)「:github
No improvement in speed was observed with our reactive apps (the Gatling results are even slightly worse).
數月後,看似相反的結論卻在DZone17一篇名爲《Raw Performance Numbers - Spring Boot 2 Webflux vs. Spring Boot 1》18的文中出現,測試結果是 Spring Boot 2 WebFlux在高併發下響應時間更爲平穩。實際上,這個測試結論有些」關公戰秦瓊「的味道,畢竟 Spring Boot 2.0 下的 WebFlux 和 Spring Boot 1.0 中的 Servlet 容器所使用線程模型是不一樣的,而且 Servlet 3.0 異步以及非阻塞特性缺省是關閉的。不過以上兩篇的結論並不矛盾,前者關注於響應速度,後者則強調吞吐量,都是性能的核心指標。遺憾的是,兩篇文章均未對各自的測試用例作出調優,所以以上結論都存在必定的侷限性,這也是本人對 Reactive 技術可否提高性能提出質疑的地方。web
若是本人是國內提出 Reactive 問題的第一人的話,那麼知秋19就是國內第一個解決問題的人。做爲國內爲數很少的 Reactive 以及 NIO 方面的專家,在技術研究上,他追求格物致知,不輕忽技術細節。在知識分享上,他可謂是知無不言,言無不盡,不只在社交羣中答疑解惑,並且錄製免費視頻,發佈在 B 站20以及 YouTube 頻道21,並獲得 Josh Long 等大佬的推文(Twitter)。或許以上方式還不足以完整地討論 Java Reactive 技術,知秋選擇了漫長而又艱苦的著書之路,儘管他是本人的朋友,然而 」內舉不避親「,筆者推薦給讀者朋友,首先是由於這是大陸地區第一本全面解讀 Java Reactive 技術的書籍,除做者的雄厚技術積累背書以外,書中的知識脈絡是按部就班的。同時,這也是一本引人深思的書,本書在導讀源碼的同時,也引導讀者對於代碼設計上的思考。再者,這又是一本知識苦旅的書,由於它涉及面較廣,讀者不只須要具有必定的 Java 併發以及面向對象設計,並且須要讀者付出較多的時間去反覆推敲。正所謂」夫夷以近,則遊者衆;險以遠,則至者少「22,筆者但願讀者在購買此書後,不輕言放棄,當您面臨挑戰時,那纔是成長的開始。同時,也期盼讀者將 Reactive 技術付之於實踐,提前觸碰將來。spring
小馬哥(mercyblitz)23apache
2019 年 3 月 5 日編程
-《Java編程⽅方法論:響應式RxJava與代碼設計實戰》
-《高可⽤可伸縮微服務架構:基於Dubbo、Spring Cloud和Service Mesh》
-《Spring Boot 編程思想(核⼼篇)》segmentfault
深刻探討 Java 相關技術,包括行業動態,架構設計,設計模式,框架使用,源碼分析等。
SegmentFault 直播
慕課視頻
慕課網