java Spring WebFlux 和 Reactor 的线程模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45019486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 08:27:57  来源:igfitidea点击:

Threading model of Spring WebFlux and Reactor

javamultithreadingreactive-programmingproject-reactorspring-webflux

提问by Florian Beaufumé

Currently experimenting reactive programming with Spring 5.0.0.RC2, Reactor 3.1.0.M2and Spring Boot 2.0.0.M2.

目前正在使用Spring 5.0.0.RC2Reactor 3.1.0.M2Spring Boot 2.0.0.M2试验反应式编程。

Wondering about the concurrency and threading modelused by WebFlux and Reactor to properly code the application and handle the mutable state.

想知道WebFlux 和 Reactor 用于正确编码应用程序和处理可变状态的并发和线程模型

The Reactor doc states that the library is considered concurrency agnostic and mentions the Scheduler abstraction. The WebFlux doc does not give information.

Reactor 文档指出该库被认为是并发不可知的,并提到了调度程序抽象。WebFlux 文档没有提供信息。

Yet when using WebFlux through Spring Boot, a threading model is defined.

然而,当通过 Spring Boot 使用 WebFlux 时,定义了一个线程模型。

From my experimentations here is what I got:

从我的实验中,我得到了:

  • The model is neither 1 event thread, nor 1 event thread + workers
  • Several thread pools are used
  • "reactor-http-nio-3" threads: probably one per core, handle the incoming HTTP requests
  • "Thread-7" threads: used by async requests to MongoDB or HTTP resources
  • "parallel-1" threads: one per core, created by Schedulers.parallel() from Reactor, used by delay operators and such
  • Shared mutable state must be synchronized by the application
  • ThreadLocal (for application state, MDC logging, etc) are not request scoped, so are not very interesting
  • 该模型既不是 1 个事件线程,也不是 1 个事件线程 + 工作线程
  • 使用了几个线程池
  • reactor-http-nio-3”线程:可能每个核心一个,处理传入的 HTTP 请求
  • Thread-7”线程:用于对 MongoDB 或 HTTP 资源的异步请求
  • parallel-1”线程:每个核心一个,由 Reactor 的 Schedulers.parallel() 创建,由延迟运算符等使用
  • 共享的可变状态必须由应用程序同步
  • ThreadLocal(用于应用程序状态、MDC 日志记录等)不是请求范围的,所以不是很有趣

Is this correct ? What is the concurrency and threading model of WebFlux: for example what are the default thread pools?

这个对吗 ?WebFlux 的并发和线程模型是什么:例如默认线程池是什么?

Thank you for the information

感谢您的信息

采纳答案by metaphori

After the question, the present documentation does provide some clues about the concurrency modeland the threads one could expect (but I still think that clearer/better descriptions of what happens under-the-scene from a multi-threading perspective would be highly appreciated by Spring newcomers).

在提出问题之后,目前的文档确实提供了一些关于并发模型和人们可以预期的线程的线索(但我仍然认为从多线程的角度对场景下发生的事情进行更清晰/更好的描述将受到高度赞赏春季新人)。

It discusses the difference between Spring MVC and Spring WebFlux (1-thread-per-request model vs. event-loop):

它讨论了 Spring MVC 和 Spring WebFlux 之间的区别(1-thread-per-request 模型与事件循环):

In Spring MVC, and servlet applications in general, it is assumed that applications may block the current thread, e.g. for remote calls, and for this reason servlet containers use a large thread pool, to absorb potential blocking during request handling.

In Spring WebFlux, and non-blocking servers in general, it is assumed that applications will not block, and therefore non-blocking servers use a small, fixed-size thread pool (event loop workers) to handle requests. Invoking a Blocking API

在 Spring MVC 和一般的 servlet 应用程序中,假设应用程序可能会阻塞当前线程,例如远程调用,因此 servlet 容器使用大型线程池,以吸收请求处理期间潜在的阻塞。

在 Spring WebFlux 和一般的非阻塞服务器中,假设应用程序不会阻塞,因此非阻塞服务器使用一个小的、固定大小的线程池(事件循环工作者)来处理请求。调用阻塞 API

But notice that Spring MVC apps can also introduce some asynchronicity (cf., Servlet 3 Async). And I suggest this presentationfor a discussion wrt Servlet 3.1 NIO and WebFlux.

但请注意,Spring MVC 应用程序也可以引入一些异步性(参见 Servlet 3 Async)。我建议将此演示文稿用于讨论 Servlet 3.1 NIO 和 WebFlux。

Back to the docs: it also suggests that, when working with reactive streams, you have some control:

回到文档:它还表明,在使用反应式流时,您有一些控制权:

What if you do need to use a blocking library?

Both Reactor and RxJava provide the publishOn operator to continue processing on a different thread.

如果确实需要使用阻塞库怎么办?

Reactor 和 RxJava 都提供了 publishOn 操作符来在不同的线程上继续处理。

(For more details on this, refer to scheduling in Reactor)

(有关更多详细信息,请参阅Reactor 中的调度

It also discusses the threads you may expect in WebFlux applications (boldis mine):

它还讨论了您在 WebFlux 应用程序中可能期望的线程(粗体是我的):

Threading Model

What threads should you expect to see on a server running with Spring WebFlux?

  • On a "vanilla" Spring WebFlux server (e.g. no data access, nor other optional dependencies), you can expect one thread for the server, and several others for request processing (typically as many as the number of CPU cores). Servlet containers, however, may start with more threads (e.g. 10 on Tomcat), in support of both servlet, blocking I/O and servlet 3.1, non-blocking I/O usage.
  • The reactive WebClientoperates 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 and RxJava provide thread pool abstractions, called Schedulers, to use with the publishOn operator that is used to switch processing to a different thread pool. The schedulers have names that suggest a specific concurrency strategy, e.g. "parallel" for CPU-bound workwith a limited number of threads, or "elastic" for I/O-bound workwith a large number of threads. If you see such threads it means some code is using a specific thread pool Scheduler strategy.
  • Data access libraries and other 3rd party dependencies may also create and use threads of their own.

线程模型

您希望在运行 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 运算符一起使用。该调度有提出一个具体的并发策略的名称,如“平行”的CPU限制的工作与线程的数量有限,或“弹性”为I / O密集型工作,有大量的线程。如果您看到此类线程,则意味着某些代码正在使用特定的线程池调度程序策略。
  • 数据访问库和其他第 3 方依赖项也可以创建和使用它们自己的线程

In part, you can configure the details of the threading model via configuration

部分地,您可以通过配置来配置线程模型的细节

To configure the threading model for a server, you'll need to use server-specific config APIs, or if using Spring Boot, check the Spring Boot configuration options for each server. The WebClient can be configured directly. For all other libraries, refer to their respective documentation.

要为服务器配置线程模型,您需要使用特定于服务器的配置 API,或者如果使用 Spring Boot,请检查每个服务器的 Spring Boot 配置选项。WebClient 可以直接配置。对于所有其他库,请参阅它们各自的文档。

Moreover, as e.g. the discussion Default number of threads in Spring boot 2.0 reactive webflux configurationhighlights,

此外,例如讨论 Spring boot 2.0 反应式 webflux 配置中的默认线程数突出显示,

The default number of threads for request handling is determined by the underlying web server; by default, Spring Boot 2.0 is using Reactor Netty, which is using Netty's defaults

请求处理的默认线程数由底层 Web 服务器决定;默认情况下,Spring Boot 2.0 使用 Reactor Netty,它使用 Netty 的默认值

it is a matter of default components and their defaults (and overall configuration, including that injected transparently through annotations) -- which may also change across versions of Spring/Boot and corresponding dependencies. Said that, your guesses seem correct.

这是默认组件及其默认值(以及整体配置,包括通过注释透明注入的配置)的问题——这也可能在 Spring/Boot 和相应依赖项的版本之间发生变化。说到这里,你的猜测似乎是正确的。