首页 > 解决方案 > Spring Webflux 或非阻塞模式不能不利于扩展

问题描述

我明白了线程是非阻塞的,我们不需要根据 N 个并发请求让线程蔓延,而是我们将我们的任务放在我们的响应式 Web 编程模式中的单个事件循环中。

是的,这会有所帮助,但是由于事件循环是一个队列,如果要处理的第一个任务永远阻塞怎么办?然后事件循环将永远不会进行,因此除了排队更多任务之外,响应和处理将结束。是的,超时可能是可能的,但我无法理解事件循环如何成为一个好的解决方案。

假设您有 3 个任务需要 3 秒来等待 IO 并运行每个执行并将它们提交到事件队列。然后它们仍然需要 9 秒才能被处理并在 IO 解决后执行。在使线程阻塞的情况下,这将在 3 秒内解决,因为它们同时运行。

我可以看到一个好处是,如果事件循环不是真正的队列,并且在发出任务已准备好处理的信号时,它会分派该任务以进行处理。但是,在这种情况下,这意味着任务执行的顺序不会被维护,并且每个任务仍然必须运行一个线程才能判断 IO 何时解决。

也许我没有正确理解事件循环和线程处理。有人可以纠正我吗,因为看起来这种反应堆模式似乎让事情变得更糟。

最后,在 Spring Reactor 中的 X 请求时,是否只创建 1 个线程来运行处理程序而不是传统的 X 线程?在那种情况下,如果有人不小心写了阻塞代码,那是不是意味着每个后续请求都会排队?

标签: javaspringspring-bootreactive-programmingproject-reactor

解决方案


将事件循环用于长时间运行的任务并不是一个好主意。这被认为是一种反模式。通常它仅用于快速获取即将发生的事件,但如果工作会明显阻塞事件循环,则不会实际执行与这些事件相关的工作。您可能希望使用单独的线程池来执行长时间运行的任务。因此,事件循环通常只会使用异步的非阻塞结构来启动工作(或者只有在可以非常快速完成的情况下才真正完成工作)并将较重且可能阻塞的任务传递给单独的线程池(用于 CPU 密集型计算) 或操作系统(例如要通过网络发送的数据缓冲区)。

此外,不要被只有一个线程在处理事件这一事实所迷惑,它非常快,通常对于要求苛刻的应用程序来说也足够了。NodeJS 之类的平台或 Netty 之类的框架(用于 Akka、Play 框架、Apache Cassandra 等)在其核心使用事件循环并取得了巨大成功。人们应该意识到一个事实,在事件循环中执行阻塞操作通常是一个坏主意。

请查看其中一些帖子以获取更多信息:


推荐阅读