反应式框架中的线程建模

Thread modeling in reactive frameworks

我有一个与反应式框架的线程建模相关的问题,例如 Vert.x。

因此,像 Vert.x 这样的框架致力于让主线程与核心数量相同的想法,这样就不需要太多的上下文切换,因为它是一项代价高昂的操作。然后我们将一切都建模为事件。例如,传入的 http 请求是一个事件,从 DB 接收响应也是一个事件等等。想法是确保主线程上的处理程序任务 运行 不会阻塞,如果我们确实有一些耗时的东西,那么将它放在工作线程上。例如,虽然传入的 http 请求在主线程上处理,但从数据库中获取服务该请求所需的数据是在工作线程上完成的。

但是它是如何解决上下文切换的问题的。与这种方法一样,我们可以轻松拥有大量并发工作线程,这需要上下文切换。

那么这里的赢家究竟是什么?

在 Vert.x 这样的反应式框架中,使用框架提供的 API 的 I/O 操作不会阻塞线程。因此,当您发出 HTTP 请求或从数据库中获取数据(使用非阻塞数据库驱动程序)时,工作不会发送到工作线程。 I/O 请求在后台运行,不会阻塞你的事件循环线程(或任何其他线程),一旦响应可用,框架就会负责执行你的回调,完成未来等。所以在不需要阻塞操作的应用程序,上下文切换非常少,因为单个线程可以同时进行 运行 许多 I/O 操作(因此服务许多请求)而不会阻塞。

仅当您必须执行长运行 阻塞操作时才需要工作线程。这方面的示例包括昂贵的数学计算、解析大量文本或使用阻塞 I/O 的 API(如 JDBC API)。在这些情况下,您可以使用工作线程或线程池来进行阻塞,以便事件循环保持空闲状态以服务于其他请求。虽然通常您会使用小型工作线程池,但您确实会在这里支付上下文切换惩罚,因此 运行 线程的数量不应很大。

因此,要获得减少上下文切换的好处,您必须确保您的应用程序主要使用本机非阻塞 APIs。