Spring WebFlux学习记录
概述
- 传统的基于 Servlet 的 Web 框架,如 Spring MVC,在本质上都是阻塞和多线程的,每个连接都会使用一个线程。在请求处理的时候,会在线程池中拉取一个工作者( worker )线程来对请求进行处理。同时,请求线程是阻塞的,直到工作者线程提示它已经完成为止。
Spring WebFlux 是异步、非阻塞的 WEB 模块,支持 Reactive Streams 背压,并在 Netty、Undertow 和 Servlet 容器等服务器上运行。
通常它们只需要与 CPU 核⼼数量相同的线程。通过使⽤所谓的事件轮询(event looping)机制,这些框架能够⽤⼀个线程处理很多请求,这样每次连接的成本会更低。在事件轮询中,所有事情都是以事件的⽅式来进⾏处理的,包括请求以及密集型操作(如数据库和⽹络操作)的回调。当需要执⾏成本⾼昂的操作时,事件轮询会为该操作注册⼀个回调,这样操作可以并⾏执⾏,⽽事件轮询则会继续处理其他的事件
为什么要创建 Spring WebFlux?
- 需要一个非阻塞的 Web 栈来处理少量线程的并发,并以较少的硬件资源进行扩展。
- 函数式编程。Spring WebFlux 能够在注解的 controller 的同时提供函数式的 Web 端点。
Spring MVC 依赖于 Servlet 阻塞式 I/O,并让应用程序在需要时直接使用 Servlet API。Spring WebFlux 依赖于 Servlet 的非阻塞 I/O,并在一个低级别的适配器后面使用 Servlet API。它没有被暴露出来以供直接使用。
响应式
reactive(响应式):指的是围绕对变化做出反应的编程模型— 对 I/O 事件做出反应的网络组件,对鼠标事件做出反应的 UI controller
Reactor 是 Spring WebFlux 的首选响应式库。它提供了 Mono 和 Flux API 类型,通过与 ReactiveX 运算符词汇 相一致的丰富运算符集,对 0..1(Mono)和 0..N(Flux)的数据序列进行操作
关于 Reactor 的介绍请移步我关于 Reactor 的相关文档,会有详细的介绍
WebFlux 需要 Reactor 作为核心依赖,但它可以通过 Reactive Streams 与其他响应式库互操作。一般来说,WebFlux API 接受一个普通的 Publisher 作为输入,在内部将其调整为 Reactor 类型,使用该类型,并返回 Flux 或 Mono 作为输出。因此,你可以传递任何 Publisher 作为输入,你可以在输出上应用操作,但你需要调整输出,以便与另一个响应式库一起使用。
编程模型
- 注解式 COntroller:与 Spring MVC 一致,基于 spring-web 模块的相同注解。Spring MVC 和 WebFlux Controller 都支持响应式(Reactor 和 RxJava)返回类型,因此,要区分它们并不容易。
- 函数式端点:基于 Lambda 的、轻量级的、函数式的编程模型。你可以把它看成是一个小型的库或一组实用程序,应用程序可以用它来路由和处理请求。和注解式 controller 的最大区别是,应用程序从头到尾负责处理请求,而不是通过注解声明意图并被回调。
核心
HttpHandler
HttpHandler 是一个简单的契约,有一个处理请求和响应的单一方法。 用于 HTTP 请求处理的基本约定,具有非阻塞 I/O 和 Reactive Streams 背压,以及 Reactor Netty、Undertow、Tomcat、Jetty 和任何 Servlet 容器的适配器。
WebHandler API
WebHandler API 的目标是提供一套更广泛的在 Web 应用程序中常用的功能,用于处理请求的通用 web API,在此基础上建立具体的编程模型,如注解 controller 和函数式端点。
过滤器
在 WebHandler API, 中,你可以使用 WebFilter 在过滤器和目标 WebHandler 的其他处理链之前和之后应用拦截式逻辑
DispatcherHandler
与 Spring MVC 类似,Spring WebFlux 也是围绕 front controller 模式设计的,其中一个中央 WebHandler,即 DispatcherHandler,为请求处理提供一个共享算法,而实际工作则由可配置的委托组件执行。
DispatcherHandler 从 Spring 配置中发现了它所需要的委托组件。它也被设计成 Spring Bean 本身,并实现了 ApplicationContextAware 以访问它所运行的 context。
实现:
1 | // org.springframework.web.reactive.DispatcherHandler#handle |

