当前位置: 首页 > 知识库问答 >
问题:

Spring WebFlux和Reactor的线程模型

宰父保臣
2023-03-14

目前正在使用Spring 5.0.0.rc2、Reactor 3.1.0.m2和Spring Boot 2.0.0.m2进行反应编程实验。

对WebFlux和Reactor所使用的并发和线程模型感到疑惑,以正确地对应用程序进行编码并处理可变状态。

Reactor doc声明库被认为是并发不可知的,并且提到了调度器抽象。WebFlux文档不提供信息。

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

从我的实验中我得到的是:

  • 模型既不是1个事件线程,也不是1个事件线程+工作者
  • 使用了多个线程池
  • reactor-http-nio-3”线程:可能每个核心一个线程,处理传入的HTTP请求
  • “Thread-7”线程:由对MongoDB或HTTP资源的异步请求使用
  • “Parallel-1”线程:每个核心一个线程,由来自Reactor的Schedulers.Parallel()创建,由延迟运算符等使用
  • 共享可变状态必须由应用程序同步
  • ThreadLocal(用于应用程序状态、MDC日志记录等)不属于请求范围,因此不太有趣

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

谢谢你提供的信息

共有1个答案

花和宜
2023-03-14

在这个问题之后,目前的文档提供了一些关于并发模型和您所期望的线程的线索(但我仍然认为,从多线程的角度对场景下发生的事情进行更清晰/更好的描述将会受到Spring新手的高度赞赏)。

它讨论了Spring MVC和Spring WebFlux之间的区别(每个请求1线程模型与事件循环):

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

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

但是请注意Spring MVC应用程序也可以引入一些异步性(参见Servlet3 Async)。我建议将此演示作为讨论WRTServlet3.1NIO和WebFlux。

回到文档:它还建议,在处理反应流时,您可以进行一些控制

(有关此方面的更多详细信息,请参阅反应堆中的调度)

它还讨论了您可能在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提供线程池抽象(称为调度器),与用于将处理切换到不同线程池的publishOn运算符一起使用。调度器的名称暗示了特定的并发策略,例如,“Parallel”用于具有有限数量线程的CPU绑定工作,或“Elastic”用于具有大量线程的I/O绑定工作。如果看到这样的线程,则表示某些代码正在使用特定的线程池调度器策略。
  • 数据访问库和其他第三方依赖项也可以创建和使用自己的线程。

在一定程度上,您可以通过配置来配置线程模型的细节

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

此外,正如讨论Spring Boot2.0 reactive webflux配置中的默认线程数所强调的,

 类似资料:
  • 目前正在使用Spring 5.0.0.rc2、Reactor 3.1.0.m2和Spring Boot 2.0.0.m2进行反应编程实验。 对WebFlux和Reactor所使用的并发和线程模型感到疑惑,以正确地对应用程序进行编码并处理可变状态。 Reactor doc声明库被认为是并发不可知的,并且提到了调度器抽象。WebFlux文档不提供信息。 然而,当通过Spring Boot使用WebFl

  • 早期除了reactor线程外,还设置了writer写成,用于监听worker进程的PIPE,写回TCP客户端。 1.6.12后将这2个角色做了合并,直接在reactor进程内监听PIPE,写回TCP客户端。 合并后的好处是,recv/send/close都是在同一个线程内完成的,不存在之前复杂的时序问题。一切变得更加简单了。另外outbuffer和sendfile也可以更轻松实现。 swoole_

  • 反应器-http-epoll-1 reactor-http-epoll-2 reactor-http-epoll-3 reactor-http-epoll-4 我知道我可以使用Reactor调度器来卸载阻塞工作。我的问题更多的是--这4个线程是什么,我们在哪里有这种配置?

  • 之前提到Vert.x API是事件驱动 - 当他们都可用时,Vert.x传递事件给处理程序。 在大多数情况下Vertx要求使用一种称为event loop线程的处理程序。 如无有 Vert.x 或您的应用程序块中,event loop可以欢快地运行将事件传递给不同的处理程序提供事件陆续到达。 因为没有阻塞,event loop可以在短时间内提供大量的事件。例如一个单一的event loop可以非常

  • 本章介绍 线程模型的总览 EventLoop 并发 任务执行 任务调度 线程模型定义了应用或者框架如何执行你的代码,所以选择线程模型极其重要。Netty 提供了一个简单强大的线程模型来帮助我们简化代码。所有 ChannelHandler,包括业务逻辑,都保证由一个 Thread 同时执行特定的 Channel。这并不意味着Netty不能使用多线程,只是 Netty 限制每个Channel 都由一个

  • 前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个重要组件和Reactor的对应关系,在后面的章节中可能还会提到本节介绍的基本概念。 1 Reactor的事件处理机制 首先来回想一下普通函数调用的机制:程序调用某函数?函数执行,程序等待?函数将结果和控制权返回给程序?程序继续处理。 Reactor释义“反应堆”