《Java編程方法論:響應式RxJava與代碼設計實戰》序

原文鏈接:《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“ 的口號。

或許開源界的種種舉動無法說服您向 Reactive 的”港灣“中停靠,不過 Java 9 Flow API4 的引入,又給業界注入了一劑強心針。不難看出,無論是 Java API,還是 Java 框架均走向了 Reactive 編程模型的道路,這並非是一種巧合。

通常,人們談到的 Reactive 可與 Reactive 編程劃上等號,以”非阻塞(Non-Blocking)“和”異步(Asynchronous)“的特性並述,數據結構與操作相輔相成。Reactive 涉及函數式和併發兩種編程模型,前者關注語法特性,後者強調執行效率。簡言之,Reactive 編程的意圖在於 ”Less Code,More Efficient“。除此之外,個人認爲 Reactive 更大的價值在於統一 Java 併發編程模型,使得同步和異步的實現代碼無異,同時做到 Java 編程風格與其他編程語言更好地融合,或許您也發現 Java 與 JS 在 Reactive 方面並不存在本質區別。縱觀 Java 在 Reactive 編程上的發展而看,其特性更新可謂是步步爲營,如履薄冰。儘管 Java 線程 API ThreadRunnable 就已具備異步以及非阻塞的能力,然而同步和異步編程的模式並不統一,並且理解 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,還是 Reactor6Stream 操作方法卻又相形見絀。值得一提的是,這些操作方法在 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文中的總結:

Reactive Programming 作爲觀察者模式(Observer) 的延伸,不同於傳統的命令編程方式( Imperative programming)同步拉取數據的方式,如迭代器模式(Iterator) 。而是採用數據發佈者同步或異步地推送到數據流(Data Streams)的方案。當該數據流(Data Steams)訂閱者監聽到傳播變化時,立即作出響應動作。在實現層面上,Reactive Programming 可結合函數式編程簡化面嚮對象語言語法的臃腫性,屏蔽併發實現的複雜細節,提供數據流的有序操作,從而達到提升代碼的可讀性,以及減少 Bugs 出現的目的。同時,Reactive Programming 結合背壓(Backpressure)的技術解決發佈端生成數據的速率高於訂閱端消費的問題。

不難看出,Reactive 是一門綜合的編程藝術,在實現框架的加持下,相同的代碼邏輯實現同步和異步非阻塞功能,從而達到提升應用整體性能的目的。不過現實的情況或許沒有那麼理想,Spring 官方文檔在《Web on Reactive Stack》章節中提到,"Reactive 和非阻塞通常並不是讓應用運行的更快"14

Reactive and non-blocking generally do not make applications run faster.

爲此,JHipster15 給出了一份《 Spring 5 WebFlux 性能測試報告》16,其中一條結論是,”Reactive 應用並沒有表現出速度提升(甚至是變得更差)“:

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 技術能否提升性能提出質疑的地方。

如果本人是國內提出 Reactive 問題的第一人的話,那麼知秋19就是國內第一個解決問題的人。作爲國內爲數不多的 Reactive 以及 NIO 方面的專家,在技術研究上,他追求格物致知,不輕忽技術細節。在知識分享上,他可謂是知無不言,言無不盡,不僅在社交羣中答疑解惑,而且錄製免費視頻,發佈在 B 站20以及 YouTube 頻道21,並得到 Josh Long 等大佬的推文(Twitter)。或許以上方式還不足以完整地討論 Java Reactive 技術,知秋選擇了漫長而又艱苦的著書之路,儘管他是本人的朋友,然而 ”內舉不避親“,筆者推薦給讀者朋友,首先是因爲這是大陸地區第一本全面解讀 Java Reactive 技術的書籍,除作者的雄厚技術積累背書之外,書中的知識脈絡是循序漸進的。同時,這也是一本引人深思的書,本書在導讀源碼的同時,也引導讀者對於代碼設計上的思考。再者,這又是一本知識苦旅的書,因爲它涉及面較廣,讀者不僅需要具備一定的 Java 併發以及面向對象設計,而且需要讀者付出較多的時間去反覆推敲。正所謂”夫夷以近,則遊者衆;險以遠,則至者少“22,筆者希望讀者在購買此書後,不輕言放棄,當您面臨挑戰時,那纔是成長的開始。同時,也期盼讀者將 Reactive 技術付之於實踐,提早觸碰未來。

小馬哥(mercyblitz)23

2019 年 3 月 5 日

書籍推薦

-《Java編程⽅方法論:響應式RxJava與代碼設計實戰》
-《高可⽤可伸縮微服務架構:基於Dubbo、Spring Cloud和Service Mesh》
-《Spring Boot 編程思想(核⼼心篇)》

線上分享

免費分享

收費分享

深入探討 Java 相關技術,包括行業動態,架構設計,設計模式,框架使用,源碼分析等。

參考資源


  1. Architecture and Design InfoQ Trends Report - January 2019 - https://www.infoq.com/article...
  2. Josh (@starbuxman) is the Spring Developer Advocate at Pivotal and a Java Champion - https://spring.io/team/jlong
  3. The Reactive Manifesto - https://www.reactivemanifesto...
  4. https://docs.oracle.com/javas...
  5. RxJava: Reactive Extensions for the JVM - https://github.com/ReactiveX/...
  6. Reactor is a fully non-blocking reactive programming foundation for the JVM, with efficient demand management (in the form of managing "backpressure"). - https://github.com/reactor/re...
  7. Observer Pattern - http://en.wikipedia.org/wiki/...
  8. Iterator Pattern - https://en.wikipedia.org/wiki...
  9. Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure. - https://www.reactive-streams....
  10. Handling streams of data—especially “live” data whose volume is not predetermined - https://github.com/reactive-s...
  11. Backpressure is an integral part of this model in order to allow the queues which mediate between threads to be bounded. The benefits of asynchronous processing would be negated if the backpressure signals were synchronous (see also the Reactive Manifesto), therefore care has been taken to mandate fully non-blocking and asynchronous behavior of all aspects of a Reactive Streams implementation. - https://github.com/reactive-s...
  12. RxJava Scheduler - http://reactivex.io/documenta... Reactor Schedulers : https://projectreactor.io/doc...
  13. 《Reactive Programming 一種技術,各自表述》:https://mercyblitz.github.io/...
  14. 1.1.6. Performance - https://docs.spring.io/spring...
  15. JHipster -https://www.jhipster.tech/
  16. 《Spring 5 WebFlux: Performance tests》- https://blog.ippon.tech/sprin...
  17. DZone : https://dzone.com
  18. 《Raw Performance Numbers - Spring Boot 2 Webflux vs. Spring Boot 1》 - https://dzone.com/articles/ra...
  19. 知秋,本書的作者筆名
  20. https://space.bilibili.com/24...
  21. https://www.youtube.com/chann...
  22. 《遊褒禪山記》,王安石
  23. 小馬哥,Java 勸退師Apache Dubbo PPMC、Spring Cloud Alibaba 項目架構師 - https://mercyblitz.github.io/...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章