摘要:原文鏈接編程方法論響應式與代碼設計實戰序,來自于微信公眾號次靈均閣正文內容在一月的架構和設計趨勢報告中,響應式編程和函數式仍舊編列在第一季度的早期采納者中。
原文鏈接:《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 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文中的總結:
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 編程思想(核?篇)》
「小馬哥技術周報」
斗魚直播
B 站錄播
「慕課網」
Spring Boot 2.0深度實踐-初遇Spring Boot
Spring Boot 2.0深度實踐之系列總覽
「SegmentFault」
「小馬哥 2019 跨年直播」一入 Java 深似海,從此“勸退”成必然
收費分享「小馬哥 Java 知識星球」
深入探討 Java 相關技術,包括行業動態,架構設計,設計模式,框架使用,源碼分析等。
SegmentFault 直播
《Java 微服務實踐 - Spring Boot / Spring Cloud》
《一入 Java 深似海》
慕課視頻
《Spring Boot 2.0深度實踐之核心技術篇》
慕課網
Spring Boot 2.0深度實踐之核心技術篇
Spring Boot 2.0深度實踐之生態整合篇(即將上線...)
參考資源文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77834.html
摘要:響應式編程在介紹前,我們先聊聊響應式編程。響應式編程的一個關鍵概念是事件。今天,響應式編程最通用的一個場景是我們的移動必須做出對網絡調用用戶觸摸輸入和系統彈框的響應。并于年二月份正式向外展示了。 轉載請注明出處:https://zhuanlan.zhihu.com/p/20687178 RxJava系列1(簡介) RxJava系列2(基本概念及使用介紹) RxJava系列3(轉換操作...
摘要:讓你收獲滿滿碼個蛋從年月日推送第篇文章一年過去了已累積推文近篇文章,本文為年度精選,共計篇,按照類別整理便于讀者主題閱讀。本篇文章是今年的最后一篇技術文章,為了讓大家在家也能好好學習,特此花了幾個小時整理了這些文章。 showImg(https://segmentfault.com/img/remote/1460000013241596); 讓你收獲滿滿! 碼個蛋從2017年02月20...
摘要:中使用了提供的原生接口對自身的異步化做了改進。可以支持和兩種調用方式。實戰通過下面的例子,可以看出的最大好處特性。 showImg(https://segmentfault.com/img/remote/1460000020032427?w=1240&h=655); 前段時間工作上比較忙,這篇文章一直沒來得及寫,本文是閱讀《Java8實戰》的時候,了解到Java 8里已經提供了一個異步...
閱讀 2380·2019-08-30 15:56
閱讀 1038·2019-08-30 15:55
閱讀 3202·2019-08-30 15:44
閱讀 932·2019-08-30 10:53
閱讀 1887·2019-08-29 16:33
閱讀 2467·2019-08-29 16:13
閱讀 719·2019-08-29 12:41
閱讀 874·2019-08-26 13:56