WebFlux是一個(gè)基于反應(yīng)式編程模型的Web框架,它提供了一種處理高并發(fā)和高吞吐量的Web應(yīng)用程序的解決方案。本文將介紹WebFlux的概念、反應(yīng)式編程的核心API和編程模型,并探討學(xué)習(xí)WebFlux的重要性。
WebFlux是什么?
WebFlux是Spring5添加的一個(gè)新模塊,是一個(gè)使用響應(yīng)式編程和異步非阻塞的Web開(kāi)發(fā)框架,它的功能和Spring MVC類似,但是它可以更好地利用多核處理器和高并發(fā)連接,提高系統(tǒng)的吞吐量和伸縮性。它完全無(wú)阻塞,支持反應(yīng)流反向壓力,可在 Netty、Undertow 和 Servlet 3.1+ 容器等服務(wù)器上運(yùn)行。核心是基于Reactor的相關(guān)API實(shí)現(xiàn)的。
什么是反應(yīng)式編程?
- 反應(yīng)式一詞指的是圍繞對(duì)變化做出反應(yīng)而構(gòu)建的編程模型,如網(wǎng)絡(luò)組件對(duì) I/O 事件做出反應(yīng)、用戶界面控制器對(duì)鼠標(biāo)事件做出反應(yīng)等。從這個(gè)意義上說(shuō),非阻塞就是反應(yīng)式,因?yàn)槲覀儸F(xiàn)在的模式是在操作完成或數(shù)據(jù)可用時(shí)對(duì)通知做出反應(yīng),而不是被阻塞。
- 同時(shí)反應(yīng)式與非阻塞反向壓力建立了聯(lián)系。在同步的命令式代碼中,阻塞調(diào)用是一種自然的反向壓力,它迫使調(diào)用者等待。而在非阻塞代碼中,控制事件的速度就變得非常重要,這樣快速的生產(chǎn)者就不會(huì)壓倒其消費(fèi)者(目的地)。
- 反應(yīng)流(Reactive Streams)是一種規(guī)范(Java 9 也采用了這種規(guī)范),它定義了異步組件與反向壓力之間的交互。例如,數(shù)據(jù)存儲(chǔ)庫(kù)(作為發(fā)布者)可以生成數(shù)據(jù),然后 HTTP 服務(wù)器(作為訂閱者)可以將數(shù)據(jù)寫(xiě)入響應(yīng)。反應(yīng)流的主要目的是讓訂閱者控制發(fā)布者生成數(shù)據(jù)的快慢。
WebFlux是如何實(shí)現(xiàn)響應(yīng)式編程的?
- WebFlux是基于Reactor庫(kù)的,Reactor是一個(gè)實(shí)現(xiàn)了響應(yīng)式流規(guī)范的Java庫(kù),它提供了Flux和Mono兩種類型的數(shù)據(jù)流,分別表示多個(gè)和單個(gè)的異步數(shù)據(jù)源。WebFlux使用Flux和Mono來(lái)處理Web請(qǐng)求和響應(yīng),以及與數(shù)據(jù)庫(kù)和其他服務(wù)的交互,從而實(shí)現(xiàn)了端到端的異步非阻塞的處理流程。
- WebFlux支持兩種編程模式,一種是基于注解的,類似于Spring MVC,使用?
@Controller
?和?@RequestMapping
?等注解來(lái)定義控制器和路由;另一種是基于函數(shù)式的,使用?RouterFunction
?和?HandlerFunction
?來(lái)編寫(xiě)更靈活和函數(shù)式的代碼。
WebFlux有什么優(yōu)勢(shì)和局限性?
- WebFlux的主要優(yōu)勢(shì)是可以提高Web應(yīng)用的性能和效率,特別是在IO密集型和高并發(fā)的場(chǎng)景下,WebFlux可以使用更少的線程和資源來(lái)處理更多的請(qǐng)求,從而減少延遲和內(nèi)存占用。WebFlux也可以更好地適應(yīng)微服務(wù)和云原生的架構(gòu),因?yàn)樗梢愿菀椎貙?shí)現(xiàn)服務(wù)間的異步通信和流式處理。
- WebFlux的主要局限性是它需要使用響應(yīng)式編程的思維和技巧來(lái)編寫(xiě)和理解代碼,這對(duì)于習(xí)慣了同步阻塞編程的開(kāi)發(fā)者來(lái)說(shuō)可能有一定的學(xué)習(xí)曲線和挑戰(zhàn)。WebFlux也需要與其他支持響應(yīng)式編程的庫(kù)和框架配合使用,例如Reactor,RxJava,Spring Data Reactive等,否則可能會(huì)出現(xiàn)阻塞或不兼容的問(wèn)題。
應(yīng)用示例
環(huán)境配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
注意: 不要再引spring-boot-starter-web包,否則默認(rèn)還是使用的Servlet棧
基于注解
@RestController
@RequestMapping("/demos")
public class DemoController {
private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
@GetMapping("/index")
public Mono<String> index() {
logger.info("start {}, {}", Thread.currentThread().getName(), System.currentTimeMillis()) ;
// 這里是我們需要返回的值,在Servlet棧中直接返回具體的值,但在WebFlux中需要用Mono或Flux將數(shù)據(jù)進(jìn)行包裝
Mono<String> result = Mono.just(666) ;
logger.info("end {}, {}", Thread.currentThread().getName(), System.currentTimeMillis()) ;
return result;
}
}
基于注解的方式處理返回值不一樣外其它與傳統(tǒng)的WebMVC一樣。
基于函數(shù)式
@Bean
public RouterFunction<ServerResponse> router1() {
return RouterFunctions.route()
.GET("/r1", request -> {
String id = request.queryParam("id").orElse(null) ;
if ("2".equals(id)) {
throw new RuntimeException("Router Param id Error...") ;
}
return ServerResponse.ok().bodyValue("你輸入的是id = " + id) ;
}).build() ;
}
函數(shù)式,我們只需像定義普通的bean一樣即可,返回值為?RouterFucntion<ServerResponse>
?。
HandlerFunction
? 處理:該函數(shù)接收 ?ServerRequest
? 并返回延遲的 ?ServerResponse
?(即 ?Mono<ServerResponse>
?)。請(qǐng)求和響應(yīng)對(duì)象都不可變。?HandlerFunction
? 相當(dāng)于基于注解的編程模型中 ?@RequestMapping
? 方法的主體。
總結(jié)
WebFlux作為一種新一代的Web框架,具有響應(yīng)式能力、非阻塞I/O和函數(shù)式編程風(fēng)格等優(yōu)勢(shì)。它適用于需要處理高并發(fā)和高吞吐量的應(yīng)用場(chǎng)景,并在微服務(wù)架構(gòu)和云原生應(yīng)用開(kāi)發(fā)中表現(xiàn)出色。然而,學(xué)習(xí)和采用WebFlux可能需要一些時(shí)間和精力,并且在遷移到WebFlux時(shí)需要考慮現(xiàn)有代碼的調(diào)整和遷移工作。因此,您應(yīng)該根據(jù)您的項(xiàng)目需求和團(tuán)隊(duì)的技術(shù)能力來(lái)決定是否值得學(xué)習(xí)和采用WebFlux。了解其特點(diǎn)和優(yōu)勢(shì),并與團(tuán)隊(duì)進(jìn)行討論和評(píng)估,以做出明智的決策。
如果你對(duì)編程知識(shí)和相關(guān)職業(yè)感興趣,歡迎訪問(wèn)編程獅官網(wǎng)(http://hgci.cn/)。在編程獅,我們提供廣泛的技術(shù)教程、文章和資源,幫助你在技術(shù)領(lǐng)域不斷成長(zhǎng)。無(wú)論你是剛剛起步還是已經(jīng)擁有多年經(jīng)驗(yàn),我們都有適合你的內(nèi)容,助你取得成功。