自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解鎖異步響應力量:淺析Spring WebFlux

開發(fā) 架構
談到Spring WebFlux就需要著重解釋下響應式編程模型,響應式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。它倡導使用異步數(shù)據(jù)流來構建事件驅(qū)動的、可擴展的應用程序。

1.WebFlux簡介

Spring WebFlux是Spring框架的一個模塊,用于構建反應式、異步和事件驅(qū)動的應用程序。它提供了一種基于Reactive Streams標準的編程模型,能夠處理大量并發(fā)請求和高吞吐量,同時具有較低的資源消耗。

傳統(tǒng)的Servlet API和Spring MVC是基于同步阻塞式編程模型的,而Spring WebFlux則是基于響應式編程模型的,相比較下有如下優(yōu)勢:

并發(fā)處理:

  • Servlet API和Spring MVC:采用同步阻塞IO模型,每個請求都會占用一個線程,如果有大量的長時間IO操作或者并發(fā)請求,會導致線程資源耗盡。
  • Spring WebFlux:采用非阻塞IO模型,在IO操作完成前不會阻塞線程,因此能夠更高效地處理大量并發(fā)請求。

編程模型:

  • Servlet API和Spring MVC:基于Servlet規(guī)范,通常使用注解或者配置文件來定義控制器和URL映射。
  • Spring WebFlux:提供了注解式編程和函數(shù)式編程兩種風格的路由定義方式,使得開發(fā)者可以選擇更適合自己項目的方式進行開發(fā)。

線程模型:

  • Servlet API和Spring MVC:每個請求需要綁定一個線程,線程池負責管理這些線程。
  • Spring WebFlux:基于事件驅(qū)動和響應式流,不需要為每個請求分配獨立線程,能夠更有效地利用系統(tǒng)資源。

應用場景:

  • Servlet API和Spring MVC:更適合傳統(tǒng)的同步IO應用,如CRUD操作等。
  • Spring WebFlux:適合處理I/O密集型應用,如服務器推送事件、WebSocket通信以及需要處理大量并發(fā)請求的場景。

2.響應式編程

談到Spring WebFlux就需要著重解釋下響應式編程模型,響應式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。它倡導使用異步數(shù)據(jù)流來構建事件驅(qū)動的、可擴展的應用程序。在響應式編程中,數(shù)據(jù)和事件以流的形式進行處理,并且整個系統(tǒng)會對這些流式數(shù)據(jù)進行監(jiān)聽和響應。主要優(yōu)勢如下:

  • 異步和非阻塞:響應式編程采用異步編程模型,能夠更高效地利用系統(tǒng)資源,同時避免線程阻塞,提高系統(tǒng)的并發(fā)處理能力。
  • 事件驅(qū)動:通過訂閱數(shù)據(jù)流和事件,系統(tǒng)能夠更靈活地響應外部輸入,適合處理實時性要求高的場景。
  • 可擴展性:采用反應式編程模型可以輕松地構建可擴展的系統(tǒng),因為它強調(diào)組件間的解耦和消息傳遞。
  • 簡潔清晰:響應式編程模型通常使用函數(shù)式風格,代碼更加簡潔清晰,易于理解和維護。

舉個例子:

假設我們需要實時獲取多個城市的天氣數(shù)據(jù)并展示給用戶,這就涉及到了異步獲取數(shù)據(jù)和實時推送數(shù)據(jù)給前端的需求。

在傳統(tǒng)的同步編程模型中,如果我們采用每個城市一個線程的方式來獲取天氣數(shù)據(jù),可能會因為網(wǎng)絡IO等待而造成大量線程阻塞,浪費系統(tǒng)資源。而且隨著城市數(shù)量的增多,線程管理和資源利用將變得更加困難。

通過采用響應式編程模型,我們可以將天氣數(shù)據(jù)看作一個反應式流,通過訂閱這個數(shù)據(jù)流,可以實時地獲取各個城市的天氣信息。當某個城市的天氣數(shù)據(jù)發(fā)生變化時,系統(tǒng)能夠及時地向訂閱者發(fā)送新的數(shù)據(jù),從而實現(xiàn)實時更新。

另外,由于天氣數(shù)據(jù)的獲取和推送是異步非阻塞的,不需要為每個城市的天氣數(shù)據(jù)分配獨立的線程,能夠更高效地利用系統(tǒng)資源,提高系統(tǒng)的并發(fā)處理能力。

3.Spring WebFlux核心組件

Spring WebFlux 框架由以下核心組件組成:

(1)Handler

Handler是Spring WebFlux中用于處理請求的核心組件。它可以是一個函數(shù)式的處理器,也可以是一個注解式的控制器(類似于Spring MVC中的Controller)。當接收到一個HTTP請求時,WebFlux會根據(jù)路由規(guī)則把請求映射到對應的Handler上,然后由Handler來實際處理請求并生成響應。在函數(shù)式編程風格中,Handler通常是一個處理器函數(shù),而在注解式編程中,Handler通常是一個帶有@RequestMapping注解的控制器方法。

(2)核心控制器DispatcherHandler

核心控制器DispatcherHandler等同于阻塞方式的DispatcherServlet,DispatcherHandler實現(xiàn)ApplicationContextAware,那么必然會調(diào)用setApplicationContext方法。

public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        initStrategies(applicationContext);
    }
}

initStrategies初始化

獲取HandlerMapping,HandlerAdapter,HandlerResultHandler的所有實例

protected void initStrategies(ApplicationContext context) {
    //獲取HandlerMapping及其子類型的bean
    //HandlerMapping根據(jù)請求request獲取handler執(zhí)行鏈
    Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerMapping.class, true, false);
 
    ArrayList<HandlerMapping> mappings = new ArrayList<>(mappingBeans.values());
    //排序
    AnnotationAwareOrderComparator.sort(mappings);
    this.handlerMappings = Collections.unmodifiableList(mappings);
 
    //獲取HandlerAdapter及其子類型的bean
    Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerAdapter.class, true, false);
 
    this.handlerAdapters = new ArrayList<>(adapterBeans.values());
    //排序
    AnnotationAwareOrderComparator.sort(this.handlerAdapters);
 
    //獲取HandlerResultHandler及其子類型的bean
    Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
            context, HandlerResultHandler.class, true, false);
 
    this.resultHandlers = new ArrayList<>(beans.values());
    AnnotationAwareOrderComparator.sort(this.resultHandlers);
}

DispatcherHandler的總體流程

  • 通過HandlerMapping(和DispatcherServlet中的HandlerMapping不同)獲取到HandlerAdapter放到ServerWebExchange的屬性中
  • 獲取到HandlerAdapter后觸發(fā)handle方法,得到HandlerResult
  • 通過HandlerResult,觸發(fā)handleResult,針對不同的返回類找到不同的HandlerResultHandler如視圖渲染ViewResolutionResultHandler、ServerResponseResultHandler、ResponseBodyResultHandler、ResponseEntityResultHandler不同容器有不同的實現(xiàn),如Reactor,Jetty,Tomcat等。

(3)Router

Router用于定義URL路由規(guī)則,將請求映射到對應的Handler上。它負責根據(jù)請求的URL路徑和HTTP方法找到對應的Handler,并將請求轉發(fā)給該Handler進行處理。Router可以通過多種方式定義,包括函數(shù)式路由定義和注解式路由定義。在函數(shù)式編程風格中,我們可以使用Java 8的lambda表達式和RouterFunctions來定義路由規(guī)則;而在注解式編程中,我們可以使用類似@RequestMapping和@RestController這樣的注解來定義路由規(guī)則。

(4)RouterFunction

RouterFunction是用于定義路由規(guī)則的主要接口,它可以將HTTP請求映射到對應的處理函數(shù)。通過RouterFunction,我們可以根據(jù)請求的URL路徑和HTTP方法找到對應的Handler,并將請求轉發(fā)給該Handler進行處理。

@Configuration
public class RouterConfig {

    @Bean
    public RouterFunction<ServerResponse> helloRouterFunction(HelloHandler helloHandler) {
        return route(GET("/hello"), helloHandler::handleHello);
    }
}

在這段示例代碼中,我們首先通過@Configuration注解標記了RouterConfig類,使其成為Spring的配置類。然后,我們使用@Bean注解定義了一個名為helloRouterFunction的Bean,它返回一個RouterFunction<ServerResponse>實例。

這里的route(GET("/hello"), helloHandler::handleHello)表示當收到GET請求且路徑為"/hello"時,將請求轉發(fā)給helloHandler的handleHello方法進行處理。這里使用了靜態(tài)導入,使得可以直接調(diào)用GET方法,簡化路由規(guī)則的定義。

@Component
public class HelloHandler {
    public Mono<ServerResponse> handleHello(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, WebFlux!");
    }
}

在HelloHandler類中,我們通過@Component注解標記為Spring管理的組件,并編寫了handleHello方法來處理請求。該方法返回一個Mono<ServerResponse>,在本例中是將"Hello, WebFlux!"字符串作為響應體返回給客戶端。

(5)WebHandler

WebHandler是處理請求和生成響應的抽象接口,它充當了請求和響應對象之間的橋梁。在WebFlux中,WebHandler接口定義了handle方法,用于處理ServerHttpRequest和ServerHttpResponse對象。它提供了一種統(tǒng)一的處理機制,使得不同類型的Handler可以與請求-響應生命周期進行交互。

4.選WebFlux還是Spring MVC?

首先你需要明確一點就是:WebFlux不是Spring MVC的替代方案,WebFlux并不能使接口的響應時間縮短,它僅僅能夠提升吞吐量和伸縮性 。雖然WebFlux也可以被運行在Servlet容器上(需是Servlet 3.1+以上的容器),但是WebFlux

主要還是應用在異步非阻塞編程模型,而Spring MVC是同步阻塞的,如果你目前在Spring MVC框架中大量使用非同步方案,那么,WebFlux才是你想要的,否則,使用Spring MVC才是你的首選。

在微服務架構中,Spring MVC和WebFlux可以混合使用,比如已經(jīng)提到的,對于那些IO密集型服務(如網(wǎng)關),我們就可以使用WebFlux來實現(xiàn)。


從上圖中,可以一眼看出Spring MVC和Spring WebFlux的相同點和不同點:

相同點:

  • 都可以使用Spring MVC注解,如@Controller,方便我們在兩個Web框架中自由轉換;
  • 均可以使用Tomcat,Jetty,Undertow Servlet容器(Servlet 3.1+);
  • ...

不同點:

  • Spring MVC因為是使用的同步阻塞式,更方便開發(fā)人員編寫功能代碼,Debug測試等,一般來說,如果Spring MVC能夠滿足的場景,就盡量不要用WebFlux;
  • WebFlux默認情況下使用Netty作為服務器;
  • WebFlux不支持MySql;

5.WebFlux與Spring框架集成

pom.xml:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>webflux-demo</artifactId>
    <version>1.0.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>
</project>

在上述配置中,我們使用了Spring Boot的起步依賴
spring-boot-starter-webflux來引入WebFlux相關的依賴。接下來,我們將創(chuàng)建一個簡單的Controller并將其拆分到單獨的類中。

首先,創(chuàng)建一個名為 HelloController 的類:

import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerRequest;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

public class HelloController {
    public RouterFunction<ServerResponse> route() {
        return route(GET("/hello"), this::handleHello);
    }

    private Mono<ServerResponse> handleHello(ServerRequest request) {
        return ServerResponse.ok().bodyValue("Hello, WebFlux!");
    }
}

然后在主應用程序中注入HelloController:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

@SpringBootApplication
public class WebFluxIntegrationDemo {

    public static void main(String[] args) {
        SpringApplication.run(WebFluxIntegrationDemo.class, args);
    }

    @Bean
    public RouterFunction<ServerResponse> monoRouterFunction(HelloController helloController) {
        return helloController.route();
    }
}

在這個示例中,我們通過@Bean注解將HelloController注入到主應用程序中,并且調(diào)用其route方法來定義路由規(guī)則。

6.總結

關于pring WebFlux 很多很多,本文主要總結如下幾點

優(yōu)點:

  • 非阻塞和異步:能夠處理大量并發(fā)請求,提高系統(tǒng)的吞吐量。
  • 響應式編程模型:支持響應式數(shù)據(jù)流處理,適合處理實時、事件驅(qū)動的應用場景。
  • 彈性和擴展性:能夠輕松地與反應式數(shù)據(jù)流、異步數(shù)據(jù)庫等集成,方便構建彈性和可擴展的系統(tǒng)。

缺點:

  • 學習曲線較陡峭:相對于傳統(tǒng)的Servlet編程模型,對于開發(fā)人員需要一定的學習成本。
  • 對某些傳統(tǒng)的基于Servlet的庫和框架的兼容性可能不夠理想。

適用范圍:

  • 需要處理高并發(fā)、實時性要求高的網(wǎng)絡應用程序;
  • 適合微服務架構和需要異步通信的項目;
  • 處理大規(guī)模數(shù)據(jù)流和事件驅(qū)動的應用場景。
責任編輯:姜華 來源: 今日頭條
相關推薦

2024-09-29 13:53:58

數(shù)據(jù)飛輪數(shù)據(jù)中臺數(shù)字化轉型

2021-06-02 10:39:59

ServletWebFluxSpringMVC

2010-04-14 14:14:42

Oracle用戶解鎖

2023-02-09 08:01:12

核心組件非阻塞

2022-07-04 09:15:10

Spring請求處理流程

2023-09-04 11:52:53

SpringMVC性能

2017-11-06 08:28:44

DDD架構設計IT

2022-11-04 08:39:46

SpringWebFlux

2024-06-13 00:54:19

2024-09-29 18:49:39

2021-07-28 20:13:04

響應式編程

2023-11-02 18:01:24

SpringMVC配置

2009-08-17 13:34:02

C#異步操作

2020-03-24 09:54:57

SpringMVCWebFlux

2020-07-07 07:00:00

Spring WebFREST APIReactive AP

2019-03-04 08:48:23

Spring WebFJavaIO

2022-09-26 08:54:39

Spring函數(shù)式編程

2021-07-15 11:16:31

Spring WebWebFlux架構

2009-07-28 16:40:11

ASP.NET異步頁面

2020-05-25 07:00:00

雙因素認證身份認證密碼
點贊
收藏

51CTO技術棧公眾號