什么是WebFlux

简介: 函数式编程。就像添加注释一样 在Java 5中创造了机会(例如带注释的REST控制器或单元测试),该 在Java 8中添加lambda表达式为Java中的函数式API创造了机会。 这对于非阻塞应用程序和延续式 API 来说是一个福音(正如普及的那样 by 和 ReactiveX),允许声明式 异步逻辑的组合。在编程模型级别,Java 8启用了Spring。 WebFlux 提供功能性 Web 端点以及带注释的控制器。

为什么创建Spring WebFlux?

答案是需要一个非阻塞的 Web 堆栈来处理并发 线程数量少,硬件资源少,规模小。Servlet 非阻塞 I/O 远离 Servlet API 的其余部分,其中合约是同步的 或阻塞 。这就是动机 作为跨任何非阻塞运行时的基础的新通用 API。那是 重要,因为服务器(如 Netty)在异步中建立良好, 无阻塞空间。FilterServletgetParametergetPart

另一部分是函数式编程。就像添加注释一样 在Java 5中创造了机会(例如带注释的REST控制器或单元测试),该 在Java 8中添加lambda表达式为Java中的函数式API创造了机会。 这对于非阻塞应用程序和延续式 API 来说是一个福音(正如普及的那样 by 和 ReactiveX),允许声明式 异步逻辑的组合。在编程模型级别,Java 8启用了Spring。 WebFlux 提供功能性 Web 端点以及带注释的控制器。CompletableFuture

定义“反应性”
我们谈到了“非阻塞”和“功能性”,但反应性是什么意思?

术语“响应式”是指围绕对更改做出反应而构建的编程模型 - 网络组件对 I/O 事件做出反应,UI 控制器对鼠标事件做出反应,等等。 从这个意义上说,非阻塞是被动的,因为我们现在处于模式,而不是被阻止 在操作完成或数据可用时对通知做出反应。

在Spring团队中,还有另一个重要的机制与“反应式”相关联。 这就是无阻塞背压。在同步命令性代码中,阻止调用 作为一种自然形式的背压,迫使呼叫者等待。在非阻塞中 代码,控制事件速率变得很重要,这样快速生产者就不会 压倒它的目的地。

Reactive Streams是一个小规范(在Java 9中也采用) 这定义了异步组件与背压之间的相互作用。 例如,数据存储库(充当发布服务器) 可以生成 HTTP 服务器(充当订阅者)的数据 然后可以写入响应。反应式流的主要目的是让 订阅者控制发布者生成数据的速度或速度。

常见问题:如果出版商不能放慢脚步怎么办?
反应流的目的只是建立机制和边界。 如果发布者无法放慢速度,则必须决定是缓冲、丢弃还是失败。
反应式接口
反应式流在互操作性方面起着重要作用。图书馆对此感兴趣 和基础设施组件,但作为应用程序 API 不太有用,因为它太 低级。应用程序需要一个更高级别、更丰富的功能API,以便 编写异步逻辑 — 类似于 Java 8 API,但不仅适用于集合。 这就是响应式库所扮演的角色。Stream

反应器是首选的反应库 Spring WebFlux.它提供单声道和通量 API 类型 通过一组与 运算符的 ReactiveX 词汇表。 反应器是一个反应流库,因此,它的所有运算符都支持非阻塞背压。 Reactor 非常关注服务器端 Java。它是在密切合作下开发的 与春天。MonoFlux

WebFlux需要Actor作为核心依赖项,但它可以与其他反应式反应式反应器互操作 通过反应流的库。作为一般规则,WebFlux API 接受普通作为输入,在内部将其适应 Reactor 类型,使用该类型,并返回 a 或 a 作为输出。因此,您可以将任何内容作为输入传递,并且可以应用 对输出的操作,但您需要调整输出以用于另一个反应式库。 只要可行(例如,带注释的控制器),WebFlux 就会透明地适应使用 的 RxJava 或其他响应式库。有关更多详细信息,请参阅响应式库。PublisherFluxMonoPublisher

除了 Reactive API 之外,WebFlux 还可以与 Kotlin 中的协程 API 一起使用,后者提供了一种更命令式的编程风格。 以下 Kotlin 代码示例将与协程 API 一起提供。
编程模型
该模块包含作为Spring WebFlux基础的响应式基础, 包括 HTTP 抽象、响应式流适配器(支持) 服务器、编解码器和核心 WebHandler API 可与 Servlet API,但具有非阻塞合约。spring-web

在此基础上,Spring WebFlux提供了两种编程模型的选择:

带注释的控制器:与Spring MVC一致,并基于相同的注释 从模块。Spring MVC 和 WebFlux 控制器都支持反应式 (Reactor 和 RxJava) 返回类型,因此,要区分它们并不容易。一个值得注意的 不同之处在于 WebFlux 还支持响应式参数。spring-web@RequestBody

[webflux-fn]:基于 Lambda 的轻量级函数式编程模型。你可以想到 这是一个小型库或一组实用程序,应用程序可以使用这些库来路由和 处理请求。与带注释的控制器的最大区别在于应用程序 负责从头到尾的请求处理,而不是通过声明意图 注释和被回调。

适用性
Spring MVC 还是 WebFlux?

这是一个很自然的问题,但却设置了一个不合理的二分法。实际上,两者兼而有之 共同努力,扩大可用选项的范围。两者专为 彼此的连续性和一致性,它们并排可用,并反馈 双方都受益。下图显示了两者之间的关系,它们之间的关系 有共同点,并且每个都支持独特的内容:

Spring MVC 和 Webflux Venn
我们建议您考虑以下具体要点:

如果你有一个运行良好的Spring MVC应用程序,则无需更改。 命令式编程是编写、理解和调试代码的最简单方法。 您有最大的库选择,因为从历史上看,大多数库都是阻塞的。

如果您已经在购买非阻塞Web堆栈,Spring WebFlux提供相同的功能。 执行模型与此领域的其他模型一样受益,并且还提供了服务器的选择 (Netty、Tomcat、Jetty、Undertow 和 Servlet 容器),多种编程模型可供选择 (带注释的控制器和功能性 Web 端点),以及反应式库的选择 (Reactor、RxJava 或其他)。

如果您对与Java 8 lambda一起使用的轻量级,功能性Web框架感兴趣 或 Kotlin,您可以使用 Spring WebFlux 功能 Web 端点。那也是一个不错的选择 适用于要求不太复杂的小型应用程序或微服务,可以受益 从更高的透明度和控制。

在微服务架构中,您可以将应用程序与Spring MVC混合使用。 或 Spring WebFlux 控制器或具有 Spring WebFlux 功能端点。获得支持 对于两个框架中相同的基于注释的编程模型,可以更轻松地 重用知识,同时为正确的工作选择正确的工具。

评估应用程序的一种简单方法是检查其依赖项。如果您有阻塞 持久性API(JPA,JDBC)或网络API使用,Spring MVC是最佳选择 至少对于常见架构。反应器和 RxJava 在单独的线程上执行阻塞调用,但您不会进行 大多数非阻塞 Web 堆栈。

如果你有一个调用远程服务的 Spring MVC 应用程序,请尝试反应式 . 你可以返回反应式类型(Reactor、RxJava 或其他) 直接来自Spring MVC控制器方法。每次调用的延迟越大,或者 呼叫之间的相互依赖性,好处越大。弹簧MVC控制器 也可以调用其他反应性组件。WebClient

如果你有一个庞大的团队,请记住转向非阻塞的陡峭学习曲线, 函数式和声明式编程。无需完全切换即可启动的实用方法 是使用反应式的。除此之外,从小处着手并衡量收益。 我们预计,对于广泛的应用,这种转变是不必要的。如果你是 不确定要寻找什么好处,请首先了解非阻塞 I/O 的工作原理 (例如,单线程节点上的并发.js)及其影响。WebClient

服务器
Spring WebFlux 在 Tomcat、Jetty、Servlet 容器以及 非 Servlet 运行时,如 Netty 和 Undertow。所有服务器都适应低级通用 API,以便可以跨服务器支持更高级别的编程模型。

Spring WebFlux 没有内置的支持来启动或停止服务器。但是,它是 从 Spring 配置和 WebFlux 基础架构轻松组装应用程序,并使用一些应用程序运行它 代码行。

Spring Boot 有一个 WebFlux 启动器,可以自动执行这些步骤。默认情况下,启动器使用 Netty,但通过更改您的 Maven 或 Gradle 依赖项。Spring Boot 默认为 Netty,因为它更广泛 在异步、非阻塞空间中使用,并允许客户端和服务器共享资源。

Tomcat 和 Jetty 可以与 Spring MVC 和 WebFlux 一起使用。但是请记住, 它们的使用方式非常不同。Spring MVC 依赖于 Servlet 阻塞 I/O 和 允许应用程序在需要时直接使用 Servlet API。Spring WebFlux 依赖于 Servlet 非阻塞 I/O,并在低级后面使用 Servlet API 适配器。它不会暴露在直接使用中。

强烈建议不要映射 Servlet 过滤器或在 WebFlux 应用程序的上下文中直接操作 Servlet API。 由于上面列出的原因,在同一上下文中混合阻塞 I/O 和非阻塞 I/O 将导致运行时问题。
对于Undertow,Spring WebFlux直接使用Undertow API,而不使用Servlet API。

性能
性能具有许多特征和含义。反应性和非阻塞性 不要使应用程序运行得更快。在某些情况下,它们可以 - 例如,如果使用 并行运行远程调用。但是,它需要更多的工作要做 事情的非阻塞方式,这可能会略微增加所需的处理时间。WebClient

反应式和非阻塞性的主要预期优势是能够以小的、 固定线程数和较少内存。这使得应用程序在负载下更具弹性, 因为它们以更可预测的方式扩展。但是,为了观察这些好处,您 需要有一些延迟(包括缓慢和不可预测的网络 I/O 的混合)。 这就是反应式堆栈开始显示其优势的地方,差异可能是 戏剧性的。

并发模型
Spring MVC和Spring WebFlux都支持带注释的控制器,但有一个关键 并发模型的差异以及阻塞和线程的默认假设。

在Spring MVC(以及一般的servlet应用程序)中,假设应用程序可以 阻止当前线程(例如,用于远程调用)。出于这个原因,servlet 容器 使用大型线程池来吸收请求处理期间的潜在阻塞。

在Spring WebFlux(以及一般的非阻塞服务器)中,假设应用程序 不要阻止。因此,非阻塞服务器使用小型固定大小的线程池 (事件循环工作线程)来处理请求。

“扩展”和“少量线程”可能听起来相互矛盾,但永远不要阻塞 当前线程(并依赖于回调)意味着您不需要额外的线程,因为 没有要吸收的阻止调用。
调用阻塞 API
如果您确实需要使用阻塞库怎么办?Reactor 和 RxJava 都提供了在不同线程上继续处理的运算符。这意味着有一个 轻松逃生舱口。但请记住,阻塞 API 并不适合 此并发模型。publishOn

可变状态
在 Reactor 和 RxJava 中,您可以通过运算符声明逻辑。在运行时,反应式 形成管道,其中数据在不同的阶段按顺序处理。主要优势 这是它使应用程序不必保护可变状态,因为 永远不会同时调用该管道中的应用程序代码。

线程模型
您应该期望在运行Spring WebFlux的服务器上看到哪些线程?

在“原版”Spring WebFlux 服务器上(例如,没有数据访问或其他可选的 依赖关系),您可以期望一个线程用于服务器,其他几个线程用于请求 处理(通常与 CPU 内核数一样多)。但是,Servlet 容器 可以从更多的线程开始(例如,Tomcat 上的 10 个),以支持两个 servlet(阻塞)I/O 和 servlet 3.1(非阻塞)I/O 用法。

反应式以事件循环方式运行。所以你可以看到一个小的,固定的 与此相关的处理线程数(例如,与反应器一起 网状连接器)。但是,如果 Reactor Netty 同时用于客户端和服务器,则两者 默认情况下共享事件循环资源。WebClientreactor-http-nio-

Reactor 和 RxJava 提供线程池抽象(称为调度程序),用于与用于将处理切换到不同线程池的运算符一起使用。 调度程序具有建议特定并发策略的名称,例如“并行” (对于线程数量有限的 CPU 密集型工作)或“弹性”(适用于 I/O 密集型工作 大量线程)。如果您看到此类线程,则表示某些代码正在使用 特定的线程池策略。publishOnScheduler

数据访问库和其他第三方依赖项也可以创建和使用线程 他们自己的。

配置
Spring 框架不提供对启动和停止服务器的支持。要为服务器配置线程模型, 您需要使用特定于服务器的配置 API,或者,如果您使用 Spring Boot, 检查每个服务器的 Spring 引导配置选项。您可以直接配置。 对于所有其他库,请参阅其各自的文档。WebClient

目录
相关文章
|
4天前
|
开发框架 Java API
Spring Boot与Flowable的完美整合
【4月更文挑战第20天】
56 2
|
4天前
|
前端开发 Java API
Spring5 Webflux 响应式编程
Spring5 Webflux 响应式编程
37 1
|
9月前
|
Java 应用服务中间件 API
Spring的webFlux
Spring的webFlux
87 0
|
前端开发 Java 应用服务中间件
Spring Webflux - 03 Webflux编程模型
Spring Webflux - 03 Webflux编程模型
159 0
Spring Webflux - 03 Webflux编程模型
|
算法 前端开发 Java
Spring Webflux - 02 Reactive介绍
Spring Webflux - Reactive介绍
174 0
Spring Webflux - 02 Reactive介绍
|
数据可视化 JavaScript 前端开发
Spring Boot集成Swagger2
你好看官,里面请!今天笔者讲的是Spring Boot集成Swagger2。不懂或者觉得我写的有问题可以在评论区留言,我看到会及时回复。 注意:本文仅用于学习参考,不可用于商业用途,如需转载请跟我联系。
205 1
|
前端开发 JavaScript Java
Spring-webflux 响应式编程
Spring-webflux 响应式编程
Spring-webflux 响应式编程
|
存储 前端开发 Java
Spring 5(七)Webflux
SpringWebflux 介绍, 介绍了 spring 5 新加的功能 webflux, 内容包括使用和对比 (Spring MVC), 介绍了函数式编程
122 0
|
SQL 架构师 网络协议
关于 Spring-WebFlux 的一些想法
关于 Spring-WebFlux 的一些想法
|
缓存 Java 关系型数据库
Spring WebFlux运用中的思考与对比
Spring WebFlux运用中的思考与对比