Spring Boot 2 (十):Spring Boot 中的響應式程式設計和 WebFlux 入門

ityouknow發表於2019-02-14

Spring 5.0 中釋出了重量級元件 Webflux,拉起了響應式程式設計的規模使用序幕。

WebFlux 使用的場景是非同步非阻塞的,使用 Webflux 作為系統解決方案,在大多數場景下可以提高系統吞吐量。Spring Boot 2.0 是基於 Spring5 構建而成,因此 Spring Boot 2.X 將自動繼承了 Webflux 元件,本篇給大家介紹如何在 Spring Boot 中使用 Webflux 。

為了方便大家理解,我們先來了解幾個概念。

響應式程式設計

在計算機中,響應式程式設計或反應式程式設計(英語:Reactive programming)是一種面向資料流和變化傳播的程式設計正規化。這意味著可以在程式語言中很方便地表達靜態或動態的資料流,而相關的計算模型會自動將變化的值通過資料流進行傳播。

例如,在指令式程式設計環境中,a=b+c 表示將表示式的結果賦給 a,而之後改變 b 或 c 的值不會影響 a 。但在響應式程式設計中,a 的值會隨著 b 或 c 的更新而更新。

響應式程式設計是基於非同步和事件驅動的非阻塞程式,只需要在程式內啟動少量執行緒擴充套件,而不是水平通過叢集擴充套件。

用大白話講,我們以前編寫的大部分都是阻塞類的程式,當一個請求過來時任務會被阻塞,直到這個任務完成後再返回給前端;響應式程式設計接到請求後只是提交了一個請求給後端,後端會再安排另外的執行緒去執行任務,當任務執行完成後再非同步通知到前端。

Reactor

Java 領域的響應式程式設計庫中,最有名的算是 Reactor 了。Reactor 也是 Spring 5 中反應式程式設計的基礎,Webflux 依賴 Reactor 而構建。

Reactor 是一個基於 JVM 之上的非同步應用基礎庫。為 Java 、Groovy 和其他 JVM 語言提供了構建基於事件和資料驅動應用的抽象庫。Reactor 效能相當高,在最新的硬體平臺上,使用無堵塞分發器每秒鐘可處理 1500 萬事件。

簡單說,Reactor 是一個輕量級 JVM 基礎庫,幫助你的服務或應用高效,非同步地傳遞訊息。Reactor 中有兩個非常重要的概念 Flux 和 Mono 。

Flux 和 Mono

Flux 和 Mono 是 Reactor 中的兩個基本概念。Flux 表示的是包含 0 到 N 個元素的非同步序列。在該序列中可以包含三種不同型別的訊息通知:正常的包含元素的訊息、序列結束的訊息和序列出錯的訊息。當訊息通知產生時,訂閱者中對應的方法 onNext(), onComplete()和 onError()會被呼叫。

Mono 表示的是包含 0 或者 1 個元素的非同步序列。該序列中同樣可以包含與 Flux 相同的三種型別的訊息通知。Flux 和 Mono 之間可以進行轉換。對一個 Flux 序列進行計數操作,得到的結果是一個 Mono物件。把兩個 Mono 序列合併在一起,得到的是一個 Flux 物件。

WebFlux 是什麼?

WebFlux 模組的名稱是 spring-webflux,名稱中的 Flux 來源於 Reactor 中的類 Flux。Spring webflux 有一個全新的非堵塞的函式式 Reactive Web 框架,可以用來構建非同步的、非堵塞的、事件驅動的服務,在伸縮性方面表現非常好。

非阻塞的關鍵預期好處是能夠以小的固定數量的執行緒和較少的記憶體進行擴充套件。在伺服器端 WebFlux 支援2種不同的程式設計模型:

  • 基於註解的 @Controller 和其他註解也支援 Spring MVC
  • Functional 、Java 8 lambda 風格的路由和處理

Spring Boot 2 (十):Spring Boot 中的響應式程式設計和 WebFlux 入門

如圖所示,WebFlux 模組從上到下依次是 Router Functions、WebFlux、Reactive Streams 三個新元件。

  • Router Functions 對標準的 @Controller,@RequestMapping 等的 Spring MVC 註解,提供一套 函式式風格的 API,用於建立 Router、Handler 和Filter。
  • WebFlux 核心元件,協調上下游各個元件提供 響應式程式設計 支援。
  • Reactive Streams 一種支援 背壓 (Backpressure) 的 非同步資料流處理標準,主流實現有 RxJava 和 Reactor,Spring WebFlux 整合的是 Reactor。

預設情況下,Spring Boot 2 使用 Netty WebFlux,因為 Netty 在非同步非阻塞空間中被廣泛使用,非同步非阻塞連線可以節省更多的資源,提供更高的響應度。通過比較 Servlet 3.1 非阻塞 I / O 沒有太多的使用,因為使用它的成本比較高,Spring WebFlux 開啟了一條實用的通路。

值得注意的是:支援 reactive 程式設計的資料庫只有 MongoDB, redis, Cassandra, Couchbase

Spring Webflux

Spring Boot 2.0 包括一個新的 spring-webflux 模組。該模組包含對響應式 HTTP 和 WebSocket 客戶端的支援,以及對 REST,HTML 和 WebSocket 互動等程式的支援。一般來說,Spring MVC 用於同步處理,Spring Webflux 用於非同步處理。

Spring Boot Webflux 有兩種程式設計模型實現,一種類似 Spring MVC 註解方式,另一種是基於 Reactor 的響應式方式。

快速上手

新增 webflux 依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
複製程式碼

Spring Boot 2 (十):Spring Boot 中的響應式程式設計和 WebFlux 入門

通過 IEDA 的依賴關係圖我們可以返現spring-boot-starter-webflux依賴於spring-webflux、Reactor 和 Netty 相關依賴包。

建立 Controller

@RestController
public class HelloController {

    @GetMapping("/hello")
    public Mono<String> hello() {
        return Mono.just("Welcome to reactive world ~");
    }
}
複製程式碼

通過上面的示例可以發現,開發模式和之前 Spring Mvc 的模式差別不是很大,只是在方法的返回值上有所區別。

  • just() 方法可以指定序列中包含的全部元素。
  • 響應式程式設計的返回值必須是 Flux 或者 Mono ,兩者之間可以相互轉換。

測試類

@RunWith(SpringRunner.class)
@WebFluxTest(controllers = HelloController.class)
public class HelloTests {
    @Autowired
    WebTestClient client;

    @Test
    public void getHello() {
        client.get().uri("/hello").exchange().expectStatus().isOk();
    }
}
複製程式碼

執行測試類,測試用例通過表示服務正常。啟動專案後,訪問地址:http://localhost:8080/hello,頁面返回資訊:

Welcome to reactive world ~
複製程式碼

證明 Webflux 整合成功。

以上便是 Spring Boot 整合 Webflux 最簡單的 Demo ,後續我們繼續研究 Webflux 的使用。

示例

全網最全的 Spring Boot 學習示例專案,擊下方連結即可獲取。

示例程式碼-github

示例程式碼-碼雲

相關文章