日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

学习WebFlux时常见的问题

發(fā)布時間:2023/12/18 编程问答 32 如意码农
生活随笔 收集整理的這篇文章主要介紹了 学习WebFlux时常见的问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

只有光頭才能變強(qiáng)。

文本已收錄至我的GitHub精選文章,歡迎Star:https://github.com/ZhongFuCheng3y/3y

回顧一下上篇我對WebFlux的入門,如果沒讀過的同學(xué)建議讀一下再來看本篇文章,上一篇文章花了我很多的心血~~

  • 外行人都能看懂的WebFlux,錯過了血虧

開局再來一張圖,內(nèi)容全靠編:

這篇主要寫寫我初學(xué)時對WebFlux的一些疑問,不知道大家在看上一篇文章的時候有沒有相應(yīng)的問題呢?

這次學(xué)WebFlux主要的動力是公司組內(nèi)分享,寫了一個PPT,有需要的同學(xué)在我的公眾號(Java3y)下回復(fù)“PPT”即可獲取。

一、本來就能實現(xiàn)異步非阻塞,為啥要用WebFlux?

相信有過相關(guān)了解的同學(xué)都知道,Servlet 3.1就已經(jīng)支持異步非阻塞了。

我們可以以自維護(hù)線程池的方式實現(xiàn)異步

  • 說白了就是Tomcat的線程處理請求,然后把這個請求分發(fā)到自維護(hù)的線程處理,Tomcat的請求線程返回
@WebServlet(value = "/nonBlockingThreadPoolAsync", asyncSupported = true)
public class NonBlockingAsyncHelloServlet extends HttpServlet { private static ThreadPoolExecutor executor = new ThreadPoolExecutor(100, 200, 50000L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100)); protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { AsyncContext asyncContext = request.startAsync(); ServletInputStream inputStream = request.getInputStream(); inputStream.setReadListener(new ReadListener() {
@Override
public void onDataAvailable() throws IOException { }
@Override
public void onAllDataRead() throws IOException {
executor.execute(() -> {
new LongRunningProcess().run(); try {
asyncContext.getResponse().getWriter().write("Hello World!");
} catch (IOException e) {
e.printStackTrace();
}
asyncContext.complete(); });
} @Override
public void onError(Throwable t) {
asyncContext.complete();
}
}); } }

流程圖如下:

上面的例子來源:

  • https://www.cnblogs.com/davenkin/p/async-servlet.html

簡單的方式,我們還可以使用JDK 8 提供的CompletableFuture類,這個類可以方便的處理異步調(diào)用。

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
long t1 = System.currentTimeMillis(); // 開啟異步
AsyncContext asyncContext = request.startAsync(); // 執(zhí)行業(yè)務(wù)代碼(doSomething 指的是處理耗費(fèi)時間長的方法)
CompletableFuture.runAsync(() -> doSomeThing(asyncContext,
asyncContext.getRequest(), asyncContext.getResponse())); System.out.println("async use:" + (System.currentTimeMillis() - t1));
}

要處理復(fù)雜的邏輯時,無論是回調(diào)或 CompletableFuture在代碼編寫上都會比較復(fù)雜(代碼量大,不易于看懂),而WebFlux使用的是Reactor響應(yīng)式流,里邊提供了一系列的API供我們?nèi)ヌ幚磉壿?/strong>,就很方便了。

更重要的是:

  • WebFlux使用起來可以像使用SpringMVC一樣,能夠大大減小學(xué)習(xí)成本
  • WebFlux也可以使用Functional Endpoints方式編程,總的來說還是要比回調(diào)/CompletableFuture要簡潔和易編寫。

值得一提的是:

如果Web容器使用的是Tomcat,那么就是使用Reactor橋接的servlet async api

如果Web容器是Netty,那么就是使用的Netty,天生支持Reactive

官方的推薦是使用Netty跑WebFlux

二、WebFlux性能的問題

我們從上篇文章中就發(fā)現(xiàn),瀏覽器去調(diào)用處理慢的接口,無論是該接口是同步的,還是說是異步的,返回到瀏覽器的時間都是一致的

  • 同步:服務(wù)器接收到請求,一個線程會處理請求,直到該請求處理完成,返回給瀏覽器
  • 異步:服務(wù)器接收到請求,一個線程會處理請求,然后指派別的線程處理請求,請求的線程直接空閑出來。

官網(wǎng)也說了:

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

使用異步非阻塞的好處就是:

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

好處:只需要在程序內(nèi)啟動少量線程擴(kuò)展,而不是水平通過集群擴(kuò)展。異步能夠規(guī)避文件IO/網(wǎng)絡(luò)IO阻塞所帶來的線程堆積

下面來看一下針對相同的請求量,同步阻塞和異步非阻塞的吞吐量和響應(yīng)時長對比:

注:

  • 請求量不大時(3000左右),同步阻塞多線程處理請求,吞吐量和響應(yīng)時長都沒落后。(按道理WebFlux可能還要落后一些,畢竟多做了一步處理-->將請求委派給另一個線程去做處理
  • 請求量大時,線程數(shù)不夠用,同步阻塞(MVC)只能等待,所以吞吐量要下降,響應(yīng)時長要提高(排隊)。

Spring WebFlux在應(yīng)對高并發(fā)的請求時,借助于異步IO,能夠以少量而穩(wěn)定的線程處理更高吞吐量的請求,尤其是當(dāng)請求處理過程如果因為業(yè)務(wù)復(fù)雜或IO阻塞等導(dǎo)致處理時長較長時,對比更加顯著。

三、WebFlux實際應(yīng)用

WebFlux需要非阻塞的業(yè)務(wù)代碼,如果阻塞,需要自己開線程池去運(yùn)行。WebFlux什么場景下可以替換SpringMVC呢?

  • 想要內(nèi)存和線程數(shù)較少的場景
  • 網(wǎng)絡(luò)較慢或者IO會經(jīng)常出現(xiàn)問題的場景

SpringMVC和WebFlux更多的是互補(bǔ)關(guān)系,而不是替換。阻塞的場景該SpringMVC還是SpringMVC,并不是WebFlux出來就把SpringMVC取代了。

如果想要發(fā)揮出WebFlux的性能,需要從Dao到Service,全部都要是Mono和Flux,目前官方的數(shù)據(jù)層Reactive框架只支持Redis,Mongo等幾個,沒有JDBC

目前對于關(guān)系型數(shù)據(jù)庫,Pivotal團(tuán)隊開源出R2DBC(Reactive Relational Database Connectivity),其GitHub地址為:

  • https://github.com/r2dbc

目前R2DBC支持三種數(shù)據(jù)源:

  • PostgreSQL
  • H2
  • Microsoft SQL Server

總的來說,因為WebFlux是響應(yīng)式的,要想發(fā)揮出WebFlux的性能就得將代碼全改成響應(yīng)式的,而JDBC目前是沒支持的(至少M(fèi)ySQL還沒支持),而響應(yīng)式的程序不好調(diào)試和編寫(相對于同步的程序),所以現(xiàn)在WebFlux的應(yīng)用場景還是相對較少的。

所以,我認(rèn)為在網(wǎng)關(guān)層用WebFlux比較合適(本來就是網(wǎng)絡(luò)IO較多的場景)

現(xiàn)在再回來看Spring官網(wǎng)的圖,是不是就更親切了?

參考資料:

  • [https://blog.lovezhy.cc/2018/12/29/webflux%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98/](https://blog.lovezhy.cc/2018/12/29/webflux性能問題/)

四、有必要學(xué)Functional Endpoints 編程模式嗎?

前面也提到了,WebFlux提供了兩種模式供我們使用,一種是SpringMVC 注解的,一種是叫Functional Endpoints

Lambda-based, lightweight, and functional programming model

總的來看,就是配合Lambda和流式編程去使用WebFlux。如果你問我:有必要學(xué)嗎?其實我覺得可以先放著。我認(rèn)為現(xiàn)在WebFlux的應(yīng)用場景還是比較少,等真正用到的時候再學(xué)也不是什么難事,反正就是學(xué)些API嘛~

有Lambda表達(dá)式和Stream流的基礎(chǔ),等真正用到的時候再學(xué)也不是啥問題~

以下是通過注解的方式來使用WebFlux的示例:

以下是通過Functional Endpoints的方式來使用WebFlux的示例:

路由分發(fā)器,相當(dāng)于注解的GetMapping...

UserHandler,相當(dāng)于UserController:

五、WebFlux的實際使用場景

總的來說,因為WebFlux是響應(yīng)式的,要想發(fā)揮出WebFlux的性能就得將代碼全改成響應(yīng)式的,而JDBC目前是沒支持的(至少M(fèi)ySQL還沒支持),而響應(yīng)式的程序不好調(diào)試和編寫(相對于同步的程序),老項目也不太可能把依賴直接升上Spring5.0,所以現(xiàn)在WebFlux的應(yīng)用場景還是相對較少的(個人覺得)。

網(wǎng)關(guān)層用WebFlux比較合適(本來就是網(wǎng)絡(luò)IO較多的場景)

  • SpringCloud Gateway是基于WebFlux實現(xiàn)的

最后

這次學(xué)WebFlux主要的動力是公司組內(nèi)分享,寫了一個PPT,有需要的同學(xué)在我的公眾號(Java3y)下回復(fù)“PPT”即可獲取。

本已收錄至我的GitHub精選文章,歡迎Star:https://github.com/ZhongFuCheng3y/3y

樂于輸出干貨的Java技術(shù)公眾號:Java3y。公眾號內(nèi)有300多篇原創(chuàng)技術(shù)文章、海量視頻資源、精美腦圖,關(guān)注即可獲取!

非常感謝人才們能看到這里,如果這個文章寫得還不錯,覺得「三歪」我有點東西的話 求點贊 求關(guān)注? 求分享

總結(jié)

以上是生活随笔為你收集整理的学习WebFlux时常见的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。