Spring5響應式編程

響應式編程管理需要以非阻塞方式對該數據作出響應的數據和消費者的生產者之間的異步數據流。所以,

Reactive Programming就是關於非阻塞應用程序,這些應用程序是異步和事件驅動的,並且需要少量的線程來擴展。

基於線程的框架難以構建響應式應用程序,因為基於共享可變狀態,線程和鎖定擴展應用程序涉及高度複雜性。

在Reactive Programming上下文中,“一切都是流,當流中有數據時,以非阻塞方式運行”。

1. 為什麼使用響應式編程

採用響應式編程的高級抽象技術可以提高代碼的可讀性,因此開發人員可以主要關注定義業務邏輯的事件的相互依賴關係。

在高度併發的環境中,響應模式自然地適合於消息處理,這是一個常見的企業用例。

通過強制執行反壓功能,響應式方法最適合控制生產者和消費者之間的流量,這將有助於避免內存不足問題。

對於一個或幾個線程,IO綁定任務可以以異步和非阻塞方式執行,而不阻塞當前線程。

響應式編程可以更有效地進行管理,在高交互和實時應用程序或任何操作/事件時,都可能觸發多個連接子系統的通知。

2. 響應式編程的理想應用場景

大量的交易處理服務,如銀行部門。

大型在線購物應用程序的通知服務,如淘寶。

股票價格同時變動的股票交易業務。

3. Reactive Streams

“響應流”定義了一個API規範,其中包含一組最小的接口,這些接口公開定義了非阻塞反壓力的數據流的操作和實體的方法。

隨著反壓的引入,Reactive Streams允許用戶控制發佈者的數據交換速率。

Reactive Streams API作為java.util.concurrent.Flow正式成為Java 9的一部分。

Reactive Streams主要用作互操作層

4. Spring 5用於響應編程工作

Spring-Web-Reactive模塊和Spring MVC都支持相同的@Controller編程,但Spring-Web-Reactive另外在Reactive和非阻塞引擎上執行。

Spring-Web-Reactive模塊和Spring MVC共享許多常用算法,但Spring-Web-Reactive模塊已經重新定義了許多Spring MVC契約,如HandlerMapping和HandlerAdapter,以使它們成為異步和非阻塞以及啟用被動HTTP請求和響應(以RouterFunction和HandlerFunction的形式)。

除了現有的RestTemplate外,Spring5中還推出了新的響應式WebClient。

支持響應式編程的HTTP客戶端(例如Reactor,Netty,Undertow)已適應一系列響應式ClientHttpRequest和ClientHttpResponse抽象,將請求和響應主體公開為Flux ,並在讀取和寫入方面提供完全反壓支持。

Spring 5 Framework引入了Reactor作為Reactive Streams規範的實現。

Reactor是用於在JVM上構建非阻塞應用程序的下一代響應性庫。

Spring Web Reactive使用Servlet 3.1提供非阻塞I / O,並在Servlet 3.1容器上運行。

5. Spring WebFlux提供了兩種編程模型的選擇。

1) 帶註解的控制器:這些與Spring MVC相同,還有一些Spring-Web模塊提供的附加註解。Spring MVC和WebFlux控制器都支持Reactive返回類型。另外,WebFlux還支持Reactive @RequestBody參數。

2) 函數編程模型 基於lambda的輕量級小型庫,用於公開實用程序來路由和處理請求。

6. Spring Web Reactive與Spring Web MVC

Spring 5同時提供了Spring Web Reactive(在spring-web-reactive模塊下)和Spring Web MVC(在spring-webmvc模塊下)。

儘管Spring Web Reactive和Spring Web MVC模塊共享許多算法,但由於Spring Web Reactive能夠在Reactive Streams HTTP適配器層上運行,因此它們不共享代碼。

Spring MVC執行需要Servlet容器,而Spring Web Reactive也可以在非Servlet上運行,例如Netty和Undertow。

如果一定要求使用Java 8 lambda或使用Kotlin輕量級功能性Web框架的非阻塞Web棧,則應考慮從Spring MVC應用程序切換到Spring Web Reactive。

7. 響應式編程的基本配置

這裡是pom.xml,2.0.0的M5版本和WebFlux的依賴。

< parent >
 < groupId > org.springframework.boot  groupId >
 < artifactId > spring-boot-starter-parent  artifactId >
 < version > 2.0.0.M5  version >
 parent >
< dependencies >
 < dependency >
 < groupId > org.springframework.boot  groupId >
 < artifactId > spring-boot-starter-webflux  artifactId >   dependency >
 dependencies >

8. 傳統方法與響應式方法

在傳統方法中,執行將被阻止,並將等到服務執行完成。在下面的代碼中,在第一個打印語句之後,程序執行將被阻止並等待服務執行完成。服務執行完成後,程序將繼續執行,並執行第二個打印語句。

@GetMapping("/traditional")
public List < Product > getAllProducts() {
 System.out.println("traditional 開始執行...");
 List < Product > products = prodService.getProducts("traditional");
 System.out.println("traditional 執行完成");
 return products;
}

在響應式方法中,程序執行將繼續而不等待服務執行的完成。在下面的代碼中,在第一個打印語句之後,第二個打印語句將以非阻塞方式執行,而不等待服務執行的完成。Flux流將提高產品數據的可用性。

@GetMapping(value = "/reactive", .TEXT_EVENT_STREAM_VALUE)
public Flux < Product > getAll() {
 System.out.println("使用Flux響應式請求開始執行");
 Flux < Product > fluxProducts = prodService.getProductsStream("Flux");
 System.out.println("使用Flux響應式請求完成");
 return fluxProducts;
}

9. 響應式Web客戶端

除了現有的RestTemplate之外,Spring 5還引入了Reactive WebClient。

ClientHttpRequest和ClientHttpResponse抽象將請求和響應主體公開為Flux ,並在讀和寫方面提供完全反壓支持。

Spring Core的編碼器和解碼器抽象也用於客戶端,用於將Flux的字節序列化到輸入和輸出對象。

以下是一個Reactive WebClient的示例,它調用端點並接收並處理Reactive Stream Flux對象。

@GetMapping("/accounts/{id}/alerts")
public Flux < Alert > getAccountAlerts(@PathVariable Long id) {
 WebClient webClient = new WebClient(new ReactorClientHttpConnector());
 return this.repository.getAccount(id).flatMap(account -> webClient.perform(get("/alerts/{key}", account.getKey())).extract(bodyStream(Alert.class)));
}

10. Spring5的侷限性

  • 一個響應式應用程序故障排除有點困難,並且有可能在修復一個問題時,你可能意外地阻塞了已經引入的代碼。

  • 大多數傳統的基於Java的集成庫仍然阻塞。

  • 有限的可供選擇的響應數據庫,除了少數的NoSQL數據庫(如MongoDB)外。

  • 不支持Spring Security。


分享到:


相關文章: