Spring 5.0 - WebFlux

最近在做些系統(tǒng)性能瓶頸問題的提升,所以在一些開源社區(qū)以及一些著名論壇上看到針對WebFlux的解釋和說明,這里不能說不好,總體上就是阻塞-非阻塞、性能提升速度更快、支持函數(shù)式編程反應(yīng)式編程(Reactive)...人云亦云嗎?

一 問題

這里不對一些概念性問題進(jìn)行解說,主要針對一些疑問來說明?

  1. WebFlux 是什么?
  2. WebFlux 真的快嗎?
  3. WebFlux應(yīng)用場景?

二 知其然不知其所以然

2.1 Spring MVC & Spring WebFlux

我們先來了解下WebFlux: 這是Spring.io 官網(wǎng)提供的解釋

spring-reactor.png

結(jié)合上圖,Spring再解釋說明Spring WebFlux的時候與傳統(tǒng)web開發(fā)使用的Spring MVC模型進(jìn)行了對比說明:

Spring MVC

  • Spring MVC is built on the Servlet API and uses a synchronous blocking I/O architecture whth a one-request-per-thread model.
  • Spring MVC 構(gòu)建于 Servlet API 之上,使用的是同步阻塞式 I/O 模型,什么是同步阻塞式 I/O 模型呢?就是說,每一個請求對應(yīng)一個線程去處理。

這里重點(diǎn)提示一下:

  1. 基于Servlet Contatiners 阻塞式I/O模型;
  2. a one-request-per-thread model 意思就是說:一個請求對應(yīng)一個線程去處理。

Spring WebFlux

  • Spring WebFlux is a non-blocking web framework built from the ground up to take advantage of multi-core, next-generation processors and handle massive numbers of concurrent connections

  • Spring WebFlux 是一個異步非阻塞式的 Web 框架,它能夠充分利用多核 CPU 的硬件資源去處理大量的并發(fā)請求。

2.2 Spring WebFlux

The original web framework included in the Spring Framework, Spring Web MVC, was purpose-built for the Servlet API and Servlet containers. The reactive-stack web framework, Spring WebFlux, was added later in version 5.0. It is fully non-blocking, supports Reactive Streams back pressure, and runs on such servers as Netty, Undertow, and Servlet 3.1+ containers.
Spring框架中包含的原始Web框架, Spring Web MVC是專門為Servlet API和Servlet容器而構(gòu)建的。反應(yīng)性堆棧Web框架Spring WebFlux在更高版本5.0中添加。它是完全非阻塞的,支持 Reactive Streams背壓,并在Netty,Undertow和Servlet 3.1+容器等服務(wù)器上運(yùn)行。

2.2 Why was Spring WebFlux created?

以下說明來源于官網(wǎng)

  • Part of the answer is the need for a non-blocking web stack to handle concurrency with a small number of threads and scale with fewer hardware resources. Servlet 3.1 did provide an API for non-blocking I/O. However, using it leads away from the rest of the Servlet API, where contracts are synchronous (Filter, Servlet) or blocking (getParameter, getPart). This was the motivation for a new common API to serve as a foundation across any non-blocking runtime. That is important because of servers (such as Netty) that are well-established in the async, non-blocking space.

簡單解釋說明一下

  • 就是說一部分原因需要一個非阻塞的web堆棧來處理少量線程的并發(fā)性,并使用較少的硬件資源進(jìn)行擴(kuò)展。Servlet 3.1確實(shí)提供了用于非阻塞I / O的API。但是其中約定是同步的諸如(Filter、Servlet)以及阻塞的(getParameter、getPart),所以使用Servlet 3.1可能會導(dǎo)致不在使用Servlet API 其他部分。這也同樣的會促進(jìn)一個新的通用性的API在任何非阻塞提供一個基礎(chǔ)的時機(jī)。諸如:服務(wù)器(如Netty)在異步、非阻塞空間中已經(jīng)很好地建立起來。

提煉

  1. 異步非阻塞(non-blocking web stack)
  2. 少量線程數(shù)處理并發(fā)性(handle concurrency with a small number of threads)
  3. 少量硬件資源提高伸縮性(scale with fewer hardware resources.)
  4. Servlet 3.1 提供一個非阻塞API。
  • The other part of the answer is functional programming. Much as the addition of annotations in Java 5 created opportunities (such as annotated REST controllers or unit tests), the addition of lambda expressions in Java 8 created opportunities for functional APIs in Java. This is a boon for non-blocking applications and continuation-style APIs (as popularized by CompletableFuture and ReactiveX) that allow declarative composition of asynchronous logic. At the programming-model level, Java 8 enabled Spring WebFlux to offer functional web endpoints alongside annotated controllers.

簡單解釋說明一下

  • 另一部分原因:函數(shù)式編程。與在Java5中添加注釋創(chuàng)造了機(jī)會(如帶注釋的REST控制器或單元測試)一樣,在Java8中添加lambda表達(dá)式也為Java中的功能性API創(chuàng)造了機(jī)會。這對于非阻塞的應(yīng)用程序和允許異步邏輯的聲明式組合的 (as popularized by CompletableFuture and ReactiveX) 是有益的。在編程模型級別,Java 8支持Spring WebFlux提供功能性的web端點(diǎn)和帶注釋的控制器。

提煉

  1. 函數(shù)式編程(functional programming)
  2. 反應(yīng)式(Reactive)
    了解以上背景后再說說什么是``Reactive`
  • The term, “reactive,” refers to programming models that are built around reacting to change?—?network components reacting to I/O events, UI controllers reacting to mouse events, and others. In that sense, non-blocking is reactive, because, instead of being blocked, we are now in the mode of reacting to notifications as operations complete or data.
  • 反應(yīng)式是指圍繞對變化作出反應(yīng)的編程模型,網(wǎng)絡(luò)組件對I/O事件作出反應(yīng),UI控制器對鼠標(biāo)事件作出反應(yīng),以及其他。從這個意義上說,非阻塞是被動的,因?yàn)椴皇潜蛔钄啵且圆僮魍瓿苫蛘邤?shù)據(jù)的形式響應(yīng)通知。

2.3 WebFlux 的優(yōu)勢&提升性能?

猶如上面介紹:WebFlux 內(nèi)部使用的是響應(yīng)式編程(Reactive Programming),以 Reactor 庫為基礎(chǔ), 基于異步和事件驅(qū)動,可以讓我們在不擴(kuò)充硬件資源的前提下,提升系統(tǒng)的吞吐量和伸縮性。

所以它最終解決的是在很少或者不擴(kuò)充硬件資源的前提下,提升系統(tǒng)的吞吐量和伸縮性。而不是使得應(yīng)用程序運(yùn)行的更快,更不會使得你的接口的請求響應(yīng)的時間縮短了

下面是官網(wǎng)原文:

  • Performance has many characteristics and meanings. Reactive and non-blocking generally do not make applications run faster. They can, in some cases, (for example, if using the WebClient to execute remote calls in parallel). On the whole, it requires more work to do things the non-blocking way and that can increase slightly the required pro
  • WebFlux 并不能使接口的響應(yīng)時間縮短,它僅僅能夠提升吞吐量和伸縮性
  • The key expected benefit of reactive and non-blocking is the ability to scale with a small, fixed number of threads and less memory.That makes applications more resilient under load, because they scale in a more predictable way.
  • 反應(yīng)式和非阻塞的主要預(yù)期好處是能夠使用少量、固定數(shù)量的線程和較少的內(nèi)存進(jìn)行擴(kuò)展。這使應(yīng)用程序在負(fù)載下更具彈性,因?yàn)樗鼈円愿深A(yù)測的方式擴(kuò)展。

三 WebFlux 應(yīng)用場景

上面說到了, Spring WebFlux 是一個異步非阻塞式的 Web 框架,所以,它特別適合應(yīng)用在 IO 密集型的服務(wù)中,比如微服務(wù)網(wǎng)關(guān)這樣的應(yīng)用中(Spring cloud gateway)。

3.1 Applicability : WebFlux OR Spring MVC?

官網(wǎng)給出了這么一句話:

  • Spring MVC or WebFlux?
    A natural question to ask but one that sets up an unsound dichotomy. Actually, both work together to expand the range of available options. The two are designed for continuity and consistency with each other, they are available side by side, and feedback from each side benefits both sides. The following diagram shows how the two relate, what they have in common, and what each supports uniquely:

  • 通過這段是我們可以知道,當(dāng)你問出這個問題的時候,其實(shí)這個問題本身就是已經(jīng)不合理了,所以無論是WebFlux OR Spring MVC 兩者設(shè)計(jì)旨在實(shí)現(xiàn)彼此的連續(xù)性和一致性,它們是可以并行使用。共同努力擴(kuò)大了可用選型的范圍。

3.2 Concurrency Model ( Spring MVC and Spring WebFlux)

  • Both Spring MVC and Spring WebFlux support annotated controllers, but there is a key difference in the concurrency model and the default assumptions for blocking and threads.(Spring MVC和Spring WebFlux都支持帶注釋的控制器,但是并發(fā)模型以及阻塞和線程的默認(rèn)假設(shè)存在關(guān)鍵差異。)

  • In Spring MVC (and servlet applications in general), it is assumed that applications can block the current thread, (for example, for remote calls), and, for this reason, servlet containers use a large thread pool to absorb potential blocking during request handling.(在Spring MVC(通常是Servlet應(yīng)用程序)中,假定應(yīng)用程序可以阻塞當(dāng)前線程(例如,用于遠(yuǎn)程調(diào)用),因此,servlet容器使用大線程池來吸收請求期間的潛在阻塞。處理。)

  • In Spring WebFlux (and non-blocking servers in general), it is assumed that applications do not block, and, therefore, non-blocking servers use a small, fixed-size thread pool (event loop workers) to handle requests.(在Spring WebFlux(通常是非阻塞服務(wù)器)中,假定應(yīng)用程序未阻塞,因此,非阻塞服務(wù)器使用固定大小的小型線程池(事件循環(huán)工作器)來處理請求。)

下圖是兩者的共同點(diǎn)和獨(dú)自的特性

spring-mvc-webflux.png

官網(wǎng)也提出了很多關(guān)于這方面的建議:

We suggest that you consider the following specific points:

*   如果您有運(yùn)行正常的Spring MVC應(yīng)用程序,則無需更改。命令式編程是編寫,理解和調(diào)試代碼的最簡單方法。您有最大的庫選擇空間,大多數(shù)都處于阻塞狀態(tài)。

*   如果您已經(jīng)在購買無阻塞Web堆棧,那么Spring WebFlux在此空間中提供的執(zhí)行模型優(yōu)勢與其他模型相同,并且還提供服務(wù)器選擇(Netty,Tomcat,Jetty,Undertow和Servlet 3.1+容器),選擇編程模型(帶注釋的控制器和功能性Web端點(diǎn)),以及選擇反應(yīng)式庫(Reactor,RxJava或其他).

*   如果您對與Java 8 lambda或Kotlin一起使用的輕量級功能性Web框架感興趣,可以使用Spring WebFlux功能性Web端點(diǎn)。對于要求較低復(fù)雜性的較小應(yīng)用程序或微服務(wù)(可以受益于更高的透明度和控制)而言,這也是一個不錯的選擇.

*   在微服務(wù)架構(gòu)中,您可以混合使用帶有Spring MVC或Spring WebFlux控制器或帶有Spring WebFlux功能端點(diǎn)的應(yīng)用程序。在兩個框架中都支持相同的基于注釋的編程模型,這使得重用知識變得更加容易,同時還為正確的工作選擇了正確的工具.

*   評估應(yīng)用程序的一種簡單方法是檢查其依賴關(guān)系。如果您要使用阻塞性持久性API(JPA,JDBC)或網(wǎng)絡(luò)API,則Spring MVC至少是常見體系結(jié)構(gòu)的最佳選擇。在Reactor和RxJava上在單獨(dú)的線程上執(zhí)行阻塞調(diào)用在技術(shù)上都是可行的,但是您不會充分利用非阻塞Web堆棧.

*   如果您的Spring MVC應(yīng)用程序具有對遠(yuǎn)程服務(wù)的調(diào)用,請嘗試使用active `WebClient`。您可以直接從Spring MVC控制器方法返回反應(yīng)性類型(Reactor,RxJava [或其他]每個呼叫的等待時間或呼叫之間的相互依賴性越大,好處就越明顯。Spring MVC控制器也可以調(diào)用其他反應(yīng)式組件.

*   如果您有龐大的團(tuán)隊(duì),請牢記向無阻塞,功能性和聲明性編程的過渡過程中的學(xué)習(xí)曲線陡峭。在沒有完全切換的情況下啟動的實(shí)際方法是使用電抗器`WebClient`。除此之外,從小處著手并衡量收益。我們希望,對于廣泛的應(yīng)用程序,這種轉(zhuǎn)變是不必要的。如果不確定要尋找什么好處,請先了解無阻塞I / O的工作原理(例如,單線程N(yùn)ode.js上的并發(fā)性)及其影響.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容