Spring WebFlux 是 Spring Framework 5.0中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。
Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。
(PS:所谓异步非阻塞是针对服务端而言的,是说服务端可以充分利用CPU资源去做更多事情,这与客户端无关,客户端该怎么请求还是怎么请求。)
Reactive Streams是一套用于构建高吞吐量、低延迟应用的规范。而Reactor项目是基于这套规范的实现,它是一个完全非阻塞的基础,且支持背压。Spring WebFlux基于Reactor实现了完全异步非阻塞的一套web框架,是一套响应式堆栈。
【spring-webmvc + Servlet + Tomcat】命令式的、同步阻塞的
【spring-webflux + Reactor + Netty】响应式的、异步非阻塞的
同步和异步通常用来形容一次方法调用。
同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。
异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。而,异步方法通常会在另外一个线程中,“真实”地执行着。整个过程,不会阻碍调用者的工作。
- 参考:
1 Introduction
1.1 What is Reactive Programming?
In plain terms reactive programming is about non-blocking applications that are asynchronous and event-driven and require a small number of threads to scale vertically (i.e. within the JVM) rather than horizontally (i.e. through clustering).
响应式编程是基于异步和事件驱动的非阻塞程序,只是垂直通过在 JVM 内启动少量线程扩展,而不是水平通过集群扩展。
响应式编程是使用异步数据流进行编程
响应式编程的思路大概如下:你可以用包括 Click 和 Hover 事件在内的任何东西创建 Data stream。Stream 廉价且常见,任何东西都可以是一个 Stream:变量、用户输入、属性、Cache、数据结构等等。举个例子,想像一下你的 Twitter feed 就像是 Click events 那样的 Data stream,你可以监听它并相应的作出响应。
在这个基础上,你还有令人惊艳的函数去组合、创建、
过滤这些 Streams。这就是函数式魔法的用武之地。Stream 能接受一个,甚至多个 Stream 为输入。你可以融合两个 Stream,也可以从一个 Stream 中过滤出你感兴趣的 Events 以生成一个新的 Stream,还可以把一个 Stream 中的数据值 映射到一个新的 Stream 中。
既然 Stream 在响应式编程中如此重要,那么我们就应该好好的了解它们,就从我们熟悉的"Clicks on a button" Event stream 开始。
Stream 就是一个按时间排序的 Events 序列,它可以放射三种不同的 Events:(某种类型的)Value、Error 或者一个" Completed" Signal。考虑一下"Completed"发生的时机,例如,当包含这个按钮的窗口或者视图被关闭时。
通过分别为 Value、Error、“Completed"定义事件处理函数,我们将会异步地捕获这些 Events。有时可以忽略 Error 与"Completed”,你只需要定义 Value 的事件处理函数就行。监听一个 Stream 也被称作是订阅 ,而我们所定义的函数就是观察者,Stream则是被观察者,其实就是 观察者模式。
使用响应式编程得到“双击”事件stream
灰色的方框是用来转换 Stream 函数的。首先,简而言之,我们把连续 250 ms 内的 Click 都积累到一个列表中(就是 buffer(stream.throttle(250ms) 做的事。不要在意这些细节,我们只是展示一下响应式编程而已)。结果是一个列表的 Stream ,然后我们使用 map() 把每个列表映射为一个整数,即它的长度。最终,我们使用 filter(x >= 2) 把整数 1 给过滤掉。就这样,3 个操作就生成了我们想要的 Stream。然后我们就可以订阅(“监听”)这个 Stream,并以我们所希望的方式作出反应。
A key aspect of reactive applications is the concept of backpressure(背压) which is a mechanism to ensure producers don’t overwhelm consumers.
For example in a pipeline of reactive components extending from the database to the HTTP response when the HTTP connection is too slow the data repository can also slow down or stop completely until network capacity frees up.
Reactive programming also leads to a major shift from imperative to declarative async composition of logic.(响应式编程还导致从命令式逻辑到声明式异步逻辑的重大转变) It is comparable to writing blocking code vs using the CompletableFuture from Java 8 to compose follow-up actions via lambda expressions.=
“为什么我要使用响应式编程(RP)?”
响应式编程提高了代码的抽象层级,所以你可以只关注定义了业务逻辑的那些相互依赖的事件,而非纠缠于大量的实现细节。RP 的代码往往会更加简明。
特别是在开发现在这些有着大量与数据事件相关的 UI events 的高互动性 Webapps、手机 apps 的时候,RP 的优势就更加明显。10年前,网页的交互就只是提交一个很长的表单到后端,而在前端只产生简单的渲染。Apps 就表现得更加的实时了:修改一个表单域就能自动地把修改后的值保存到后端,为一些内容"点赞"时,会实时的反应到其它在线用户那里等等。
现在的 Apps 有着大量各种各样的实时 Events,以给用户提供一个交互性较高的体验。我们需要工具去应对这个变化,而响应式编程就是一个答案。
1.2 Reactive API and Building Blocks 响应式API与构件块
Spring Framework 5 embraces Reactive Streams as the contract for communicating backpressure across async components and libraries. (Spring Framework 5将响应 式流 作为在异步组件和库之间传递背压的契约)
Reactive Streams is a specification created through industry collaboration that has also been adopted in Java 9 as java.util.concurrent.Flow.(Reactive Streams是通过行业协作创建的规范,在Java 9中也已采用java.util.concurrent.Flow。)
The Spring Framework uses Reactor internally for its own reactive support. Reactor is a Reactive Streams implementation that further extends the basic Reactive Streams Publisher contract with the Flux and Mono composable API types to provide declarative operations on data sequences of 0…N and 0…1.
The Spring Framework exposes Flux and Mono in many of its own reactive APIs. At the application level however, as always, Spring provides choice and fully supports the use of RxJava.
2 Spring WebFlux Module
Spring Framework 5 includes a new spring-webflux module. The module contains support for reactive HTTP
and WebSocket clients
as well as for reactive server web applications including REST, HTML browser, and WebSocket style interactions.
2.1 Server Side
On the server-side WebFlux supports 2 distinct programming models:
- Annotation-based with @Controller and the other annotations supported also with Spring MVC
- Functional, Java 8 lambda style routing and handling
Spring Boot Webflux 有两种编程模型实现,一种类似 Spring MVC 注解方式,另一种是使用其功能性端点方式。
Both programming models are executed on the same reactive foundation that adapts non-blocking HTTP runtimes to the Reactive Streams API. The diagram below shows the server-side stack including traditional, Servlet-based Spring MVC on the left from the spring-webmvc module and also the reactive stack on the right from the spring-webflux module.
webflux overview
左侧是传统的基于 Servlet Spring Web MVC 框架 右侧是 Spring 新引入的基于
Reactive Streams Spring 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
Web 容器的选择上, Spring WebFlux 既支持像 Tomcat Jetty 样的传统容器(前提是支持 Servlet 3.1 Non-Blocking IO API) ,又支持像 Netty Undertow 那样的异步容器
不管是何种容器, Spring WebFlux 都会将其输入输出流适配成Flux<DataBuffer>格式,以便进行统一处理。
值得一提的是,除了新的 Router Functions 接口, Spring WebFlux 同时支持使用老的Spring MVC 注解声明 Reactive Controller。 和传统的 MVC Controller 不同, Reactive Controller 操作的是非阻 ServerHttpRequest 和ServerHttpResponse ,而不再是 Spring MVC 里的
HttpServletRequest和HttpServletResponse