摘要:原文鏈接編程方法論響應(yīng)式與代碼設(shè)計實戰(zhàn)序,來自于微信公眾號次靈均閣正文內(nèi)容在一月的架構(gòu)和設(shè)計趨勢報告中,響應(yīng)式編程和函數(shù)式仍舊編列在第一季度的早期采納者中。
原文鏈接:《Java編程方法論:響應(yīng)式RxJava與代碼設(shè)計實戰(zhàn)》序,來自于微信公眾號:次靈均閣正文內(nèi)容
在《2019 一月的InfoQ 架構(gòu)和設(shè)計趨勢報告》1中,響應(yīng)式編程(Reactive Programming)和函數(shù)式(Functional Programing)仍舊編列在第一季度(Q1)的 Early Adopters(早期采納者) 中。盡管這僅是一家之言,然而不少的開發(fā)人員逐漸意識到 Reactive 之風(fēng)儼然吹起。也許您的生產(chǎn)系統(tǒng)尚未出現(xiàn) Reactive 的身影,不過您可能聽說過 Spring WebFlux 或 Netflix Hystrix 等開源框架。筆者曾請教過 Pivotal(Spring 母公司)布道師 Josh Long2:”Spring 技術(shù)棧未來的重心是否要布局在 Reactive 之上?“。對方的答復(fù)是:”沒錯,Reactive 是未來趨勢。“。同時,越來越多的開源項目開始簽署 Reactive 宣言(The Reactive Manifesto)3,并喊出 ”Web Are Reactive“ 的口號。
或許開源界的種種舉動無法說服您向 Reactive 的”港灣“中停靠,不過 Java 9 Flow API4 的引入,又給業(yè)界注入了一劑強心針。不難看出,無論是 Java API,還是 Java 框架均走向了 Reactive 編程模型的道路,這并非是一種巧合。
通常,人們談到的 Reactive 可與 Reactive 編程劃上等號,以”非阻塞(Non-Blocking)“和”異步(Asynchronous)“的特性并述,數(shù)據(jù)結(jié)構(gòu)與操作相輔相成。Reactive 涉及函數(shù)式和并發(fā)兩種編程模型,前者關(guān)注語法特性,后者強調(diào)執(zhí)行效率。簡言之,Reactive 編程的意圖在于 ”Less Code,More Efficient“。除此之外,個人認(rèn)為 Reactive 更大的價值在于統(tǒng)一 Java 并發(fā)編程模型,使得同步和異步的實現(xiàn)代碼無異,同時做到 Java 編程風(fēng)格與其他編程語言更好地融合,或許您也發(fā)現(xiàn) Java 與 JS 在 Reactive 方面并不存在本質(zhì)區(qū)別。縱觀 Java 在 Reactive 編程上的發(fā)展而看,其特性更新可謂是步步為營,如履薄冰。盡管 Java 線程 API Thread 與 Runnable 就已具備異步以及非阻塞的能力,然而同步和異步編程的模式并不統(tǒng)一,并且理解 Thread API 的細(xì)節(jié)和管理線程生命周期的成本均由開發(fā)人員概括承受。雖然 Java 5 引入 J.U.C 框架(Java 并發(fā)框架)之后, ExecutorService 實現(xiàn)減輕了以上負(fù)擔(dān)。不過開發(fā)人員仍需關(guān)注 ExecutorService 實現(xiàn)細(xì)節(jié),比如怎樣合理地設(shè)置線程池空間以及阻塞隊列又成為新的挑戰(zhàn)。為此,Java 7 又引入 ForkJoinPool API,不過此時的J.U.C 框架與 Reactive 理念仍存在距離,即使是線程安全的數(shù)據(jù)結(jié)構(gòu),也并不具備并行計算的能力,如:集合并行排序,同時操作集合的手段也相當(dāng)?shù)呢汃ぃ鄙兕愃?Map/Reduce 等操作。不過這些困難只是暫時的,終究被 Java 8 ”救贖“。Stream API 的出現(xiàn)不但具備數(shù)據(jù)操作在串行和并行間自由切換的能力,如 sequential() 以及 parallel() 方法,而且淡化了并發(fā)的特性,如 sorted() 方法即可能是傳統(tǒng)排序,亦或是并行排序。相同的設(shè)計哲學(xué)也體現(xiàn)在 Java Reactive 實現(xiàn)框架中,如同書中提及的 RxJava5 API io.reactivex.Observable 。統(tǒng)一編程模型只是 Stream 其中設(shè)計目標(biāo)之一,它結(jié)合 Lambda 語法特性,雖然提供了數(shù)量可觀的操作方法,如 flatMap() 等,然而無論對比 RxJava,還是 Reactor6 ,Stream 操作方法卻又相形見絀。值得一提的是,這些操作方法在 Reactive 的術(shù)語中稱之為操作符(Operators)。當(dāng)然框架內(nèi)建的操作符的多與寡,并非判斷其是否為 Reactive 實現(xiàn)的依據(jù)。其中決定性因素在于數(shù)據(jù)必須來源于發(fā)布方(生產(chǎn)者)的”推送(Push)“,而非消費端的”拉取(Pull)“。顯然,Stream 屬于消費端已就緒(Ready)的數(shù)據(jù)集合,并不存在其他數(shù)據(jù)推送源。不過 JVM 語言早期的 Reactive 定義處于模糊地帶,如 RxJava API 屬于觀察者模式(Observer Pattern)7的擴展,而非迭代器(Iterator Pattern)模式8的實現(xiàn)。而 Reactor 的實現(xiàn)則擁抱 Reactive Streams 規(guī)范9 ,該規(guī)范消費端對于數(shù)據(jù)的操作是被動的處理,而非主動的索。換言之,數(shù)據(jù)的到達(dá)存在著不確定性10。當(dāng)推送的數(shù)據(jù)無法得到消費端及時效應(yīng)時,Reactive 框架必須提供背壓(Backpressure)11實現(xiàn),確保消費端擁有”拒絕的權(quán)利(cancel)”。在此理論基礎(chǔ)上,Reactive Streams 規(guī)范定義了一套抽象的 API,作為 Java 9 java.util.concurrent.Flow API 的頂層設(shè)計。不過關(guān)于操作符的部分,該規(guī)范似乎不太關(guān)心,這也是為什么 RxJava 和 Reactor 均稱自身為 Reactive 擴展框架的原因,同時兩者在 API 級別提供多種調(diào)度器(Schedulers)12實現(xiàn),適配不同并發(fā)場景提供。盡管 Reactive 定義在不同的陣營之間存在差異,援引本人在《Reactive-Programming-一種技術(shù)-各自表述》13文中的總結(jié):
Reactive Programming 作為觀察者模式(Observer) 的延伸,不同于傳統(tǒng)的命令編程方式( Imperative programming)同步拉取數(shù)據(jù)的方式,如迭代器模式(Iterator) 。而是采用數(shù)據(jù)發(fā)布者同步或異步地推送到數(shù)據(jù)流(Data Streams)的方案。當(dāng)該數(shù)據(jù)流(Data Steams)訂閱者監(jiān)聽到傳播變化時,立即作出響應(yīng)動作。在實現(xiàn)層面上,Reactive Programming 可結(jié)合函數(shù)式編程簡化面向?qū)ο笳Z言語法的臃腫性,屏蔽并發(fā)實現(xiàn)的復(fù)雜細(xì)節(jié),提供數(shù)據(jù)流的有序操作,從而達(dá)到提升代碼的可讀性,以及減少 Bugs 出現(xiàn)的目的。同時,Reactive Programming 結(jié)合背壓(Backpressure)的技術(shù)解決發(fā)布端生成數(shù)據(jù)的速率高于訂閱端消費的問題。
不難看出,Reactive 是一門綜合的編程藝術(shù),在實現(xiàn)框架的加持下,相同的代碼邏輯實現(xiàn)同步和異步非阻塞功能,從而達(dá)到提升應(yīng)用整體性能的目的。不過現(xiàn)實的情況或許沒有那么理想,Spring 官方文檔在《Web on Reactive Stack》章節(jié)中提到,"Reactive 和非阻塞通常并不是讓應(yīng)用運行的更快"14:
Reactive and non-blocking generally do not make applications run faster.
為此,JHipster15 給出了一份《 Spring 5 WebFlux 性能測試報告》16,其中一條結(jié)論是,”Reactive 應(yīng)用并沒有表現(xiàn)出速度提升(甚至是變得更差)“:
No improvement in speed was observed with our reactive apps (the Gatling results are even slightly worse).
數(shù)月后,看似相反的結(jié)論卻在DZone17一篇名為《Raw Performance Numbers - Spring Boot 2 Webflux vs. Spring Boot 1》18的文中出現(xiàn),測試結(jié)果是 Spring Boot 2 WebFlux在高并發(fā)下響應(yīng)時間更為平穩(wěn)。實際上,這個測試結(jié)論有些”關(guān)公戰(zhàn)秦瓊“的味道,畢竟 Spring Boot 2.0 下的 WebFlux 和 Spring Boot 1.0 中的 Servlet 容器所使用線程模型是不同的,并且 Servlet 3.0 異步以及非阻塞特性缺省是關(guān)閉的。不過以上兩篇的結(jié)論并不矛盾,前者關(guān)注于響應(yīng)速度,后者則強調(diào)吞吐量,都是性能的核心指標(biāo)。遺憾的是,兩篇文章均未對各自的測試用例做出調(diào)優(yōu),因此以上結(jié)論都存在一定的局限性,這也是本人對 Reactive 技術(shù)能否提升性能提出質(zhì)疑的地方。
如果本人是國內(nèi)提出 Reactive 問題的第一人的話,那么知秋19就是國內(nèi)第一個解決問題的人。作為國內(nèi)為數(shù)不多的 Reactive 以及 NIO 方面的專家,在技術(shù)研究上,他追求格物致知,不輕忽技術(shù)細(xì)節(jié)。在知識分享上,他可謂是知無不言,言無不盡,不僅在社交群中答疑解惑,而且錄制免費視頻,發(fā)布在 B 站20以及 YouTube 頻道21,并得到 Josh Long 等大佬的推文(Twitter)。或許以上方式還不足以完整地討論 Java Reactive 技術(shù),知秋選擇了漫長而又艱苦的著書之路,盡管他是本人的朋友,然而 ”內(nèi)舉不避親“,筆者推薦給讀者朋友,首先是因為這是大陸地區(qū)第一本全面解讀 Java Reactive 技術(shù)的書籍,除作者的雄厚技術(shù)積累背書之外,書中的知識脈絡(luò)是循序漸進的。同時,這也是一本引人深思的書,本書在導(dǎo)讀源碼的同時,也引導(dǎo)讀者對于代碼設(shè)計上的思考。再者,這又是一本知識苦旅的書,因為它涉及面較廣,讀者不僅需要具備一定的 Java 并發(fā)以及面向?qū)ο笤O(shè)計,而且需要讀者付出較多的時間去反復(fù)推敲。正所謂”夫夷以近,則游者眾;險以遠(yuǎn),則至者少“22,筆者希望讀者在購買此書后,不輕言放棄,當(dāng)您面臨挑戰(zhàn)時,那才是成長的開始。同時,也期盼讀者將 Reactive 技術(shù)付之于實踐,提早觸碰未來。
小馬哥(mercyblitz)23
2019 年 3 月 5 日
書籍推薦-《Java編程?方法論:響應(yīng)式RxJava與代碼設(shè)計實戰(zhàn)》
-《高可?可伸縮微服務(wù)架構(gòu):基于Dubbo、Spring Cloud和Service Mesh》
-《Spring Boot 編程思想(核?篇)》
「小馬哥技術(shù)周報」
斗魚直播
B 站錄播
「慕課網(wǎng)」
Spring Boot 2.0深度實踐-初遇Spring Boot
Spring Boot 2.0深度實踐之系列總覽
「SegmentFault」
「小馬哥 2019 跨年直播」一入 Java 深似海,從此“勸退”成必然
收費分享「小馬哥 Java 知識星球」
深入探討 Java 相關(guān)技術(shù),包括行業(yè)動態(tài),架構(gòu)設(shè)計,設(shè)計模式,框架使用,源碼分析等。
SegmentFault 直播
《Java 微服務(wù)實踐 - Spring Boot / Spring Cloud》
《一入 Java 深似海》
慕課視頻
《Spring Boot 2.0深度實踐之核心技術(shù)篇》
慕課網(wǎng)
Spring Boot 2.0深度實踐之核心技術(shù)篇
Spring Boot 2.0深度實踐之生態(tài)整合篇(即將上線...)
參考資源文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/77834.html
摘要:響應(yīng)式編程在介紹前,我們先聊聊響應(yīng)式編程。響應(yīng)式編程的一個關(guān)鍵概念是事件。今天,響應(yīng)式編程最通用的一個場景是我們的移動必須做出對網(wǎng)絡(luò)調(diào)用用戶觸摸輸入和系統(tǒng)彈框的響應(yīng)。并于年二月份正式向外展示了。 轉(zhuǎn)載請注明出處:https://zhuanlan.zhihu.com/p/20687178 RxJava系列1(簡介) RxJava系列2(基本概念及使用介紹) RxJava系列3(轉(zhuǎn)換操作...
摘要:讓你收獲滿滿碼個蛋從年月日推送第篇文章一年過去了已累積推文近篇文章,本文為年度精選,共計篇,按照類別整理便于讀者主題閱讀。本篇文章是今年的最后一篇技術(shù)文章,為了讓大家在家也能好好學(xué)習(xí),特此花了幾個小時整理了這些文章。 showImg(https://segmentfault.com/img/remote/1460000013241596); 讓你收獲滿滿! 碼個蛋從2017年02月20...
摘要:中使用了提供的原生接口對自身的異步化做了改進。可以支持和兩種調(diào)用方式。實戰(zhàn)通過下面的例子,可以看出的最大好處特性。 showImg(https://segmentfault.com/img/remote/1460000020032427?w=1240&h=655); 前段時間工作上比較忙,這篇文章一直沒來得及寫,本文是閱讀《Java8實戰(zhàn)》的時候,了解到Java 8里已經(jīng)提供了一個異步...
閱讀 2389·2019-08-30 15:56
閱讀 1048·2019-08-30 15:55
閱讀 3210·2019-08-30 15:44
閱讀 939·2019-08-30 10:53
閱讀 1894·2019-08-29 16:33
閱讀 2493·2019-08-29 16:13
閱讀 726·2019-08-29 12:41
閱讀 883·2019-08-26 13:56