在提问之后,
现有文档确实提供了有关并发模型和线程的一些线索,可以预期会出现哪些线程(但我仍然认为,从多线程角度更清晰/更好的描述在幕后发生的事情将受到Spring新手的高度赞赏)。
它讨论了Spring MVC和Spring WebFlux之间的区别(1个请求模型对应一个线程与事件循环):
在Spring MVC和通常的servlet应用程序中,假定应用程序可能阻塞当前线程,例如远程调用,因此servlet容器使用大型线程池来吸收请求处理期间的潜在阻塞。
在Spring WebFlux和非阻塞服务器中,假定应用程序不会阻塞,因此非阻塞服务器使用小型固定大小的线程池(事件循环工作线程)来处理请求。调用阻塞API
但请注意,Spring MVC应用程序也可以引入一些异步性(参见Servlet 3 Async)。我建议
这个演示文稿讨论Servlet 3.1 NIO和WebFlux。
回到文档:它还建议,在使用反应流时,您具有一定的控制权:
如果确实需要使用阻塞库怎么办?
Reactor和RxJava都提供了publishOn运算符,以在不同的线程上继续处理。
关于此更多细节,请参考Reactor中的调度。
它还讨论了您可能在WebFlux应用程序中遇到的线程(加粗是我的注释):
线程模型
在运行Spring WebFlux的服务器上,您应该期望看到哪些线程?
- 在“纯净”的Spring WebFlux服务器上(例如没有数据访问或其他可选依赖项),您可以期望看到一个用于服务器和多个用于请求处理的线程(通常与CPU内核数量相同)。但是,Servlet容器可能会启动更多线程(例如,在Tomcat上启动10个线程),以支持servlet、阻塞I/O和servlet 3.1非阻塞I/O使用。
- 反应式WebClient采用事件循环风格。因此,您将看到与之相关的少量固定数量的处理线程,例如使用Reactor Netty连接器的“reactor-http-nio-”。但是,如果Reactor Netty同时用于客户端和服务器,则两者默认共享事件循环资源。
- Reactor和RxJava提供了线程池抽象,称为Schedulers,可与publishOn操作符一起使用,用于切换处理到不同的线程池。这些调度程序具有暗示特定并发策略的名称,例如“parallel”用于CPU绑定工作,具有有限数量的线程,或“elastic”用于I/O绑定工作,具有大量线程。如果您看到这些线程,这意味着某些代码正在使用特定的线程池调度程序策略。
- 数据访问库和其他第三方依赖项也可能创建并使用自己的线程。
一部分可以通过配置来配置线程模型的详细信息。
要为服务器配置线程模型,您需要使用特定于服务器的配置API,或者如果使用Spring Boot,则检查每个服务器的Spring Boot配置选项。WebClient可以直接配置。对于所有其他库,请参考其各自的文档。
此外,如讨论Spring boot 2.0响应式webflux配置中默认线程数所述,
请求处理的默认线程数由底层Web服务器确定;默认情况下,Spring Boot 2.0使用Reactor Netty,该服务器使用Netty的默认值。
这是默认组件及其默认值(以及透明地通过注释注入的整体配置)的问题 -- 这也可能会随着Spring/Boot及其相应依赖关系的版本而发生变化。话说回来,您的猜测似乎是正确的。