Spring WebFlux 和 Reactor 的线程模型
Threading model of Spring WebFlux and Reactor
目前正在使用 Spring 5.0.0.RC2、Reactor 3.1.0.M2 和 [= 试验响应式编程28=]Spring 启动 2.0.0.M2.
想知道 WebFlux 和 Reactor 使用 并发和线程模型 来正确编码应用程序和处理可变状态。
Reactor 文档声明该库被认为与并发无关,并提到了调度程序抽象。 WebFlux 文档没有提供信息。
然而,当通过 Spring Boot 使用 WebFlux 时,定义了线程模型。
从我的实验中得到的是:
- 模型既不是 1 个事件线程,也不是 1 个事件线程 + worker
- 使用了多个线程池
- "reactor-http-nio-3" 线程:可能每个核心一个,处理传入的 HTTP 请求
- "Thread-7" 线程:由对 MongoDB 或 HTTP 资源
的异步请求使用
- "parallel-1" 线程:每个核心一个,由 Schedulers.parallel() 从 Reactor 创建,由延迟运算符等使用
- 应用程序必须同步共享可变状态
- ThreadLocal(用于应用程序状态、MDC 日志记录等)不是请求范围的,因此不是很有趣
这是正确的吗? WebFlux 的并发和线程模型是什么:例如默认的线程池是什么?
谢谢你的信息
在问题之后,present documentation does provide some clues about the concurrency model 和人们可以期待的线程(但我仍然认为 clearer/better 从多线程的角度描述幕后发生的事情将是高度受到 Spring 新人的赞赏)。
它讨论了 Spring MVC 和 Spring WebFlux 之间的区别(每个请求一个线程模型与事件循环):
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 3 Async)。我建议 this presentation 讨论 Servlet 3.1 NIO 和 WebFlux。
回到文档:它还表明,在使用反应流时,您有一些控制权:
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.
(更多详情请参考scheduling in Reactor)
它还讨论了您在 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 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 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 work with a limited number of threads, or "elastic" for I/O-bound work with 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.
部分可以通过配置配置线程模型的细节
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.
此外,例如讨论
亮点,
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
这是默认组件及其默认值(以及整体配置,包括通过注释透明注入的配置)的问题——这也可能在 Spring/Boot 和相应依赖项的不同版本之间发生变化。
话虽如此,你的猜测似乎是正确的。
目前正在使用 Spring 5.0.0.RC2、Reactor 3.1.0.M2 和 [= 试验响应式编程28=]Spring 启动 2.0.0.M2.
想知道 WebFlux 和 Reactor 使用 并发和线程模型 来正确编码应用程序和处理可变状态。
Reactor 文档声明该库被认为与并发无关,并提到了调度程序抽象。 WebFlux 文档没有提供信息。
然而,当通过 Spring Boot 使用 WebFlux 时,定义了线程模型。
从我的实验中得到的是:
- 模型既不是 1 个事件线程,也不是 1 个事件线程 + worker
- 使用了多个线程池
- "reactor-http-nio-3" 线程:可能每个核心一个,处理传入的 HTTP 请求
- "Thread-7" 线程:由对 MongoDB 或 HTTP 资源 的异步请求使用
- "parallel-1" 线程:每个核心一个,由 Schedulers.parallel() 从 Reactor 创建,由延迟运算符等使用
- 应用程序必须同步共享可变状态
- ThreadLocal(用于应用程序状态、MDC 日志记录等)不是请求范围的,因此不是很有趣
这是正确的吗? WebFlux 的并发和线程模型是什么:例如默认的线程池是什么?
谢谢你的信息
在问题之后,present documentation does provide some clues about the concurrency model 和人们可以期待的线程(但我仍然认为 clearer/better 从多线程的角度描述幕后发生的事情将是高度受到 Spring 新人的赞赏)。
它讨论了 Spring MVC 和 Spring WebFlux 之间的区别(每个请求一个线程模型与事件循环):
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 3 Async)。我建议 this presentation 讨论 Servlet 3.1 NIO 和 WebFlux。
回到文档:它还表明,在使用反应流时,您有一些控制权:
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.
(更多详情请参考scheduling in Reactor)
它还讨论了您在 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 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 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 work with a limited number of threads, or "elastic" for I/O-bound work with 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.
部分可以通过配置配置线程模型的细节
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.
此外,例如讨论
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
这是默认组件及其默认值(以及整体配置,包括通过注释透明注入的配置)的问题——这也可能在 Spring/Boot 和相应依赖项的不同版本之间发生变化。 话虽如此,你的猜测似乎是正确的。