關於Spring WebFlux
一、前言
在看SpringCloud
網關的技術選型時,繞不開zuul這個組建,但是爲什麼我們選用gateway
的網關,一是因爲gateway
是Spring
的全家桶項目,另外一個重要原因,也是zuul是基於servlet實現的換言之還是同步阻塞式。
非阻塞帶來的好處不言而喻,高效利用線程資源進而提高吞吐量,基於此Spring
率先拿出針對於web
的殺手鐗,就是webflux
。而Gateway
本身就是基於webflux
基礎之上實現的,幫助我們構建一套高效的微服務網關。
1.1 基礎環境
springcloud-gateway
是基於netty運行的環境,在servlet容器環境或者把它構建爲war包運行的話是不允許的,因此在項目當中沒有必要添加spring-boot-starter-web
包。
1.2 WebFlux與Reactive Stream的關係
Reactive Streams
是規範,Reactor
實現了 Reactive Streams
【響應式編程】。
WebFlux
以 Reactor
爲基礎,實現 Web
領域的反應式編程框架
反應式編程可以理解爲事件模式或者是訂閱者模式,我們如何去實現事件模式【guava的EventBus
就是一個例子】。
1.3 SpringBoot生態支持
Spring Boot
應用程序可以用命令風格(如傳統Spring WebMVC
)或函數風格(如Spring WebFlux
)
1.4 編程方式與容器支持
服務器端,WebFlux
支持兩種不同的編程模型
Spring MVC
中使用的基於 Java 註解的方式
@RestController
public class BasicController {
@GetMapping("/hello_world")
public Mono<String> sayHelloWorld() {
return Mono.just("Hello World");
}
}
@GetMapping("")
public Flux<User> list() {
return this.userService.list();
}
- 基於
Java 8
的 lambda 表達式的函數式編程模型
在函數式編程模型中,每個請求是由一個函數來處理的, 通過接口org.springframework.web.reactive.function.server.HandlerFunction
來表示,HandlerFunction
是一個函數式接口,其中只有一個方法Mono<T extends ServerResponse> handle(ServerRequest request)
,因此可以用labmda
表達式來實現該接口,接口ServerRequest
表示的是一個HTTP
請求。通過該接口可以獲取到請求的相關信息,如請求路徑、HTTP
頭、查詢參數和請求內容等。方法 handle 的返回值是一個Mono<T extends ServerResponse>
對象。接口ServerResponse
用來表示 HTTP 響應。ServerResponse
中包含了很多靜態方法來創建不同 HTTP 狀態碼的響應對象
目前 Spring Boot 不支持在一個應用中同時使用兩種不同的編程模式
這兩種編程模型只是在代碼編寫方式上存在不同。它們運行在同樣的反應式底層架構之上,因此在運行時是相同的。
WebFlux
需要底層提供運行時的支持,WebFlux 可以運行在支持 Servlet 3.1 非阻塞 IO API 的 Servlet
容器上,或是其他異步運行時環境,如 Netty
和 Undertow
。
Tomcat7.x是Servlet3.0,Tomcat8.x是Servlet3.1。
二、技術特點
1.Spring WebFlux
是異步,非阻塞的。
2.WebFlux
有Mono
,Flux
兩種集合類型。
3.Mono
是0->1集合類型,比如Mono。
4.Flux
是1->n集合類型,比如Flux
5.Mono,Flux
都是異步處理的,而集合對象基本上是同步的。
Web Flux(Netty)跟Web MVC(Servlet)優缺點?
1.Web Flux
的效率(qps)比Web MVC
高。
2.Web Flux
的編程難度高,維護成本高,對於切面等不好編寫。
核心組件
Reactor
是JVM
的完全非阻塞反應式編程基礎,具有高效的需求管理(以管理“背壓”的形式)。它直接與Java 8功能的API,特別是整合CompletableFuture
,Stream
和 Duration
。它提供了可組合的異步序列API Flux
(用於多個元素)和Mono
(用於[0 | 1]元素),廣泛地實現了Reactive Extensions
規範。這段的重點是和Java8
結合利用lambda
表達式簡潔的優點。
1.Mono
實現Publisher
並返回0或1個元素;
2.Flux
實現Publisher
並返回N個元素。