Spring 5與Spring cloud的響應式程式設計之旅
全新的Spring Cloud Finchley GA版本是Reactive(響應式/反應式)微服務之旅的一個重要里程碑。下面是Spring的Josh Long有關Reactive Spring Cloud介紹文章:
Spring框架5.0釋出於2017年9月,這是首個引入新的Reactive程式設計支援的版本,它建立在Pivotal Reactor專案的基礎上,我們的響應流(reactive stream)是相容響應執行(reactive runtime)的,Spring Framework 5還包含大量新功能,這裡不一一列出,這裡只專注於響應式支援的功能。
什麼是響應式程式設計(Reactive Programming)?Spring為什麼要和這有關係?嗯,當你構建網路服務時,這就很重要啦。
簡而言之,Spring中服務整合的底層基礎設施已經更新,可以完全接受響應式程式設計。那麼,什麼是響應式程式設計?響應式程式設計又稱反應式式程式設計,當你開始通過網路傳輸更多資料時,比如更頻繁的REST API呼叫等會使得IO緩衝區飽和,IO會發生堵塞,產生時間延遲。
IO本身不是問題,傳統IO的使用卻是阻塞的 - 執行緒必須等待InputStream生成新的bytes。(通常迴圈執行read()讀取放入byte緩衝區)。當執行緒發生等待時,這個執行緒就不能做其他任何事情。執行緒很昂貴!
想想如何使用Java或任何其他具有相同執行緒處理方法的平臺實現傳統伺服器?如果Web伺服器tomcat的執行緒池最大有100個執行緒,當第101個請求到達時,那麼tomcat在完成處理現有100個請求之前,將沒有多餘執行緒提供第101個請求的處理。當然如果第101個請求到來之前其他請求已經處理完成(並且釋放佔有的執行緒),那就太好了!可能就不需要響應式程式設計了。如果在新請求到達之前更快地釋放執行緒,並且在這些執行緒中花費的時間主要是用於輸入/輸出,那麼就不需要響應式程式設計。
當使用微服務時,遭遇大資料以及長期會話(例如在websockets和伺服器傳送的事件以及任何其他長期維持伺服器狀態)等情況時,就會遭遇到IO堵塞了。
這種執行緒與IO的耦合其實是不必要的。幾十年來,作業系統一直支援“後臺管理”IO,並在前臺應該參與時通知前臺。實際上,Java 1.4(從2000年代早期開始)就支援NIO(Channels)了,它為我們提供了一種非同步IO機制。
在這個世界中,有專門管理IO的執行緒並在應該需要時回撥用程式碼。如果IO這裡存在延遲,那麼該執行緒可以自由移動並處理其他請求。它沒有被IO的延遲堵塞。你不需要從編寫程式碼從InputStream讀取位元組內容,位元組內容會被非同步推送給你。由此你高效率地反轉了與資料來源的互動方式。
許多專案比如來自@ NetflixOSS的RxJava、來自@Pivotal的@ProjectReactor、來自Eclipse的@vertx_project和來自@lightbend的@akkateam,都在尋求提供支援這種新非同步的響應式程式設計模型。它們都存在共同點,這些共同點都被編入了Reactive Streams規範中了,這些專案都支援這個規範。
Reactive Streams規範支援釋出者向訂閱者釋出內容。訂閱者呼叫方法onNextIT來消費使用這些被髮布的內容。訂閱者訂閱時,會給出一個Subscription物件,它用來表示可以處理多少條記錄。最後一位 - 能夠準確指定訂戶準備一次處理多少記錄的能力 - 也就是流量控制,釋出者因此不會在流量上壓垮訂閱者,提升了流處理的穩定性。在響應式程式設計的背景下,流量控制也稱為背壓backpressure。
有一個介面Processor,它只是一個橋樑; 它實現了釋出者和訂閱者兩個。Project Reactor支援兩種Publisher特殊化:
1. Flux: 傳送0-N項內容。
2. Mono:只傳送單項內容,或者沒有。
這是對IO使用方式的基本思考,因此需要在上面的每一層整合入這種新的思考方式,包括 資料訪問層、安全層、Spring Boot和微服務層。
Spring框架5.0還包括一個名為Spring WebFlux的全新的響應式Web模組(甚至支援Netty專案),它甚至提供新的函式性響應端點支援。
Spring WebFlux建立在Reactive Streams規範的基礎上,因此可以與任何其他支援庫互操作。使用響應式Spring Webflux可以和Lightbend的Akka Streams(以及Scala)進行互動。
新的Spring WebFlux元件模型首先是響應式和非同步的。它支援如websockets和伺服器傳送事件等非同步,使用方式與傳統上處理同步情況的方式相同。想要在幾納秒內傳送一條包含10條記錄的簡短JSON資料?那就用一個Publisher來做!
新增模組支援響應式程式設計
為支援響應式程式設計,新版本新增了一個名為新的響應式HTTP客戶端WebClient。
Spring Data Kay支援通過模板和儲存庫對具有非同步IO支援的資料訪問技術進行響應性資料訪問。比如下面這個程式碼可以實現Reactive Spring Data MongoDB的使用:
interface ReservationRepository extends ReactiveMongoRepository<Reservation, String> { Flux<Reservation> findByEmail(String email); } @Document @AllArgsConstructor @NoArgsConstructor @Data class Reservation { @Id private String id; private String email; } <p> |
Spring Security 5支援對傳統用例(如下所示)和OAuth的響應式身份驗證和授權:
@Bean MapReactiveUserDetailsService authentication() { // don't do this! this is a hardcoded username and password and it // would literally pain Spring Security lead @rob_winch to see this! // return new MapReactiveUserDetailsService( User.withDefaultPasswordEncoder().username("user").password("pw").roles("USER").build()); } @Bean SecurityWebFilterChain authorization(ServerHttpSecurity security) { //@formatter:off return security .csrf().disable() .httpBasic() .and() .authorizeExchange() .pathMatchers("/proxy").authenticated() .anyExchange().permitAll() .and() .build(); //@formatter:on } <p> |
無論選擇使用Spring WebFlux還是Spring MVC,Spring Boot 2將所有這些結合在一起:構建REST端點;使用Actuator;管理安全性以及其他等 。
從程式碼庫更改的角度來看,這也意味著Spring Cloud團隊需要進行多方面落地,這使得這個版本變得非常重要。
響應式程式設計與現有功能對接
新版本將響應式程式設計與現有功能進行了無縫對接:服務註冊,發現,安全性,CDC(T)和測試,訊息傳遞,微代理支援,斷路器等等。我們來看一些例子。
您可以使用新的響應式模組WebClient,它支援之前Spring Cloud的DiscoveryClient支援的任何服務註冊功能(Netflix Eureka,Hashicorp Consul,Apache Zookeeper,Cloud Foundry等)。
@Bean WebClient client(LoadBalancerExchangeFilterFunction eff) { return WebClient.builder().filter(eff).build(); } <p> |
這樣你就使用這個響應式服務登錄檔WebClient了。在以下示例中,reservation-service是存在服務登錄檔中已經被註冊的服務,不是實際的主機名。
Publisher<String> emails = client .get() .uri("http://reservation-service/reservations") .retrieve() .bodyToFlux(Reservation.class) .map(Reservation::getEmail); <p> |
你可以使用Spring Cloud Stream中的響應功能來分別消費Kafka或RabbitMQ中的主題或佇列訊息,
@Configuration @EnableBinding(Sink.class) public class MyStreamListener { @StreamListener public void incoming (@Input(Sink.INPUT) Flux<String> names ) { names .map ( x-> new Reservation( null, x)) .flatMap ( this.reservationRepository::save ) .subscribe( x -> log.info( "saved " + x.toString())); } } |
你可以使用響應式Publisher物件來通過Hystrix斷路器保護和隔離可能發生錯誤的服務呼叫。
在以下示例中,我使用響應WebClient呼叫HTTP可能會失敗,如果失敗了,我們希望能夠提供對一個回退Publisher用來返回結果,這樣我的程式碼不會丟擲任何異常。它優雅地降級了。那個斷路器很聰明,它有自己的狀態監控,如果連續多次嘗試呼叫失敗,斷路器最終將直接切換到那個回退Publisher。如果下游服務重新聯機(如果使用Cloud Foundry將會重新啟動),那麼它最終會將重新註冊到登錄檔,登錄檔將發出心跳事件,並且心跳事件將把登錄檔中服務的本地檢視刪除,客戶端將看到登錄檔中有新的例項,它將重置斷路器,關閉它,並讓下一個呼叫成功通過。
Publisher<String> emails = client .get() .uri("http://reservation-service/reservations") .retrieve() .bodyToFlux(Reservation.class) .map(Reservation::getEmail); Publisher<String> fallback = HystrixCommands .from( emails ) .eager() .commandName("emails") .fallback ( Flux.just ("EEK!") ) .build(); <p> |
響應式新篇章
Spring開啟響應式程式設計的新開端,首先從這種新開端受益的是兩個新專案:Spring Cloud Gateway和Spring Cloud Function。
Spring Cloud Gateway是我們全新的響應式API閘道器。它建立在Spring的響應支援之上。它的功能是路由客戶端請求到下游服務。這其實響應應式程式設計的一個完美用例(需求)。
以下是使用Spring Cloud Gateway將請求代理:9999/proxy到服務(通過服務登錄檔解析和負載平衡)和速率受限的示例。(注意:此配置可以存在於Spring Cloud Config Server中的(可重新整理的)配置中,或者你可以建立的任何源Flux<Route>。)
此示例將每個經過身份驗證的使用者限制為每秒100個請求。您不需要通過Spring Security來協助閘道器做這件事,但是配置中已經暗暗地這樣做了:
@Bean RouteLocator gateway (RouteLocatorBuilder rlb, RedisRateLimiter rrl) { return rlb .routes() .route( spec -> spec .path("/rl") .flters( fs -> fs .requestRateLimiter( c -> c.setRateLimiter( this.redisRateLimiter() )) .setPath("/reservations") ) .uri("lb://reservation-service/") ) .build(); } @Bean // 100 reqs per second, burstable to 150 RedisRateLimiter redisRateLimiter (){ return new RedisRateLimiter(100, 150); } <p> |
函式即服務
Spring Cloud Function是我們新的 function-as-a-service(函式即服務)的抽象。它將plain-'-functions函式調整為不同的“函式即服務”執行時所需的型別。它可用於AWS Lambda,Microsoft Azure,當然還有我們自己的Project Riff,Project Riff是Apache 2許可的基於Kubernetes的多語言“函式即服務”執行環境。
使用起來可能不容易!您需要建立java.util.function.Function<I,O>例項。包括I和O,在這種情況下,可能是Publisher<X>:
package com.example.uppercase; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import reactor.core.publisher.Flux; import java.util.function.Function; @SpringBootApplication public class UppercaseApplication { @Bean Function<Flux<String>, Flux<String>> uppercase() { return incoming -> incoming.map(String::toUpperCase); } public static void main(String[] args) { SpringApplication.run(UppercaseApplication.class, args); } } <p> |
正如你現在所希望的那樣,響應式程式設計已經在Spring中真正實現了!Spring Cloud是最終全面支援的響應性程式設計的專案。
[該貼被admin於2018-07-04 20:10修改過]
相關文章
- Spring Cloud Stream的函式式和響應式Reactive程式設計特點 - spring.ioSpringCloud函式React程式設計
- 響應式程式設計基礎教程:Spring Boot 與 Lettuce 整合程式設計Spring Boot
- Spring Boot 2 (十):Spring Boot 中的響應式程式設計和 WebFlux 入門Spring Boot程式設計WebUX
- Spring Boot 中的響應式程式設計和 WebFlux 入門Spring Boot程式設計WebUX
- Spring響應式Reactive程式設計的10個陷阱 -Jeroen RosenbergSpringReact程式設計ROS
- spring AOP 程式設計式應用Spring程式設計
- Spring Cloud Stream應用與自定義RocketMQ Binder:程式設計模型SpringCloudMQ程式設計模型
- 聊聊Spring Reactor反應式程式設計SpringReact程式設計
- 函式響應式程式設計與RxSwift函式程式設計Swift
- 二、Spring Cloud 之旅 -- Eureka 微服務的釋出與呼叫SpringCloud微服務
- Spring Cloud Feign設計原理SpringCloud
- Spring Cloud Zuul記錄介面響應資料SpringCloudZuul
- Spring 程式設計式事務管理Spring程式設計
- Spring Cloud Gateway修改請求和響應body的內容SpringCloudGateway
- java springboot spring cloud 設計方案JavaSpring BootCloud
- Spring Cloud(八)高可用的分散式配置中心 Spring Cloud ConfigSpringCloud分散式
- 使用Reactor響應式程式設計React程式設計
- Java Spring Cloud 與響應式微服務(三)客戶服務建立JavaSpringCloud微服務
- Java Spring Cloud 與響應式微服務(二)賬戶服務建立JavaSpringCloud微服務
- Java Spring Cloud 與響應式微服務(一)服務註冊中心JavaSpringCloud微服務
- Spring Cloud Stream與Spring Integration整合以及Spring Cloud Function的關係:開啟從基於註釋到函數語言程式設計的漫長轉換 - spring.ioSpringCloudFunction函數程式設計
- spring cloud微服務分散式雲架構Spring Cloud ZuulSpringCloud微服務分散式架構Zuul
- spring cloud微服務分散式雲架構-Spring Cloud NetflixSpringCloud微服務分散式架構
- spring cloud微服務分散式雲架構-Spring Cloud BusSpringCloud微服務分散式架構
- spring cloud微服務架構設計SpringCloud微服務架構
- Spring Cloud Feign設計原理(轉載)SpringCloud
- Spring Cloud與Dubbo的完美融合之手「Spring ClSpringCloud
- 響應式程式設計與MVVM架構—理論篇程式設計MVVM架構
- Spring AOP:面向切面程式設計的核心概念與實際應用Spring程式設計
- 響應式程式設計入門(RxJava)程式設計RxJava
- 響應式程式設計庫RxJava初探程式設計RxJava
- Spring Cloud Feign 應用SpringCloud
- Spring筆記(4) - Spring的程式設計式事務和宣告式事務詳解Spring筆記程式設計
- Spring Cloud Alibaba與Spring Boot、Spring Cloud之間不得不說的版本關係CloudSpring Boot
- 對響應式程式設計的懷疑 - lukaseder程式設計
- spring cloud微服務分散式雲架構 - Spring Cloud簡介SpringCloud微服務分散式架構
- Spring Cloud實戰系列(六) - 分散式配置中心Spring Cloud ConfigSpringCloud分散式
- 揚帆起航:從指令式程式設計到函式響應式程式設計程式設計函式