目前正在尝试使用 Spring 5.0.0.RC2 , Reactor 3.1.0.M2 和 Spring Boot 2.0.0.M2 进行反应式编程。
想知道WebFlux和Reactor使用的 并发和线程模型 来正确编写应用程序并处理可变状态。
Reactor文档指出该库被认为与并发无关,并提到了Scheduler抽象。WebFlux文档不提供信息。
但是,通过Spring Boot使用WebFlux时,会定义一个线程模型。
从我的实验中,我得到了:
这样对吗 ?WebFlux的并发和线程模型是什么:例如,默认的线程池是什么?
感谢您的信息
在提出问题之后,本文档的确提供了一些有关并发模型和线程可能期望的线索(但我仍然认为,从多线程的角度对幕后发生的事情进行更清晰/更好的描述将受到高度赞赏。春季新人)。
它讨论了Spring MVC和Spring WebFlux(每请求1线程模型与事件循环)之间的区别:
通常在Spring MVC和servlet应用程序中,假定应用程序可能会阻塞当前线程(例如,用于远程调用),因此,servlet容器使用大线程池来吸收请求处理期间的潜在阻塞。 在Spring WebFlux和一般非阻塞服务器中,假定应用程序不会阻塞,因此非阻塞服务器使用固定大小的小型线程池(事件循环工作程序)来处理请求。调用阻止API
通常在Spring MVC和servlet应用程序中,假定应用程序可能会阻塞当前线程(例如,用于远程调用),因此,servlet容器使用大线程池来吸收请求处理期间的潜在阻塞。
在Spring WebFlux和一般非阻塞服务器中,假定应用程序不会阻塞,因此非阻塞服务器使用固定大小的小型线程池(事件循环工作程序)来处理请求。调用阻止API
但是请注意,Spring MVC应用程序还可能引入一些异步性(请参阅Servlet 3异步)。我建议在演示文稿时讨论Servlet 3.1 NIO和WebFlux。
回到文档:它还建议在使用反应流时,您可以控制一些:
如果确实需要使用阻止库怎么办? Reactor和RxJava都提供了publishOn运算符以继续在其他线程上进行处理。
如果确实需要使用阻止库怎么办?
Reactor和RxJava都提供了publishOn运算符以继续在其他线程上进行处理。
(有关更多信息,请参阅Reactor中的调度)
它还讨论了WebFlux应用程序中可能需要的线程( 粗体 是我的):
线程模型 您期望在运行Spring WebFlux的服务器上看到哪些线程? 在“原始” Spring WebFlux服务器上(例如,没有数据访问权限,也没有其他可选的依赖项),您可以期望 该服务器有一个线程,而其他几个则用于请求处理(通常与CPU核心数一样多) 。但是,Servlet容器可能以更多线程(例如Tomcat上为10)开始,以同时支持Servlet,阻塞I / O和Servlet 3.1,即非阻塞I / O使用。 The reactive WebClient operates in event loop style. So you’ll see a small, fixed number of processing threads related to that, e.g. “reactor-http-nio-” with the Reactor Netty connector. However if Reactor Netty is used for both client and server, the two will share event loop resources by default. Reactor和RxJava提供称为 调度程序的 线程池抽象,以与 publishOn运算符 配合使用,该 运算符用于将处理切换到另一个线程池 。该 调度有提出一个具体的并发策略的名称 ,如 “平行”的CPU限制的工作 与线程的数量有限,或 “弹性”为I / O密集型工作, 有大量的线程。如果看到这样的线程,则意味着某些代码正在使用特定的线程池调度程序策略。 数据访问库和其他第三方依赖性也可以创建和使用自己的线程 。
线程模型
您期望在运行Spring WebFlux的服务器上看到哪些线程?
您可以部分地通过配置来配置线程模型的详细信息
要为服务器配置线程模型,您需要使用服务器特定的配置API,或者,如果使用Spring Boot,请检查每台服务器的Spring Boot配置选项。可以直接配置WebClient。对于所有其他库,请参阅其各自的文档。
此外,例如在Spring Boot 2.0反应式Webflux配置中的默认线程数讨论中 ,
用于请求处理的默认线程数由基础Web服务器确定。默认情况下,Spring Boot 2.0使用的是Reactor Netty,后者使用的是Netty的默认值
这是默认组件及其默认值(以及整体配置,包括通过注释透明注入的默认配置)的问题-在Spring / Boot版本和相应的依赖项之间,它们也可能会发生变化。话虽如此,您的猜测似乎是正确的。