Node.js在跨多个磁盘驱动器的文件系统I/O中的性能:是否为工作线程



我在这里读到了几个关于Node.js以非阻塞方式快速处理文件I/O操作的性能优势的问答,而不是使用具有阻塞或非阻塞请求的工作线程,但似乎没有一个能回答我的问题。

我正在编写一个Node.js应用程序,它将打开、哈希并编写存储在多个硬盘驱动器上的非常大的文件(多个gig)。我正在探索工作线程的概念,因为它们允许我将命令隔离到特定的硬盘驱动器。例如:假设我有一个线程处理将硬盘驱动器a上的一个文件复制到硬盘驱动器B,另一个线程负责将一个文件从硬盘驱动器C复制到硬盘驱动D。

假设我同时将其扩展到更多的硬盘驱动器,那么在没有工作线程的情况下使用Node.js并让它处理所有这些请求对我来说更有意义吗?或者,如果我可以按驱动器隔离I/O并同时处理多个驱动器的请求,工作线程是否更有意义?

根据我所读到的内容,工作线程似乎是显而易见的解决方案,但我也看到,只让单个Node.js进程处理一个文件I/O队列通常会更快。感谢您的指导!

编辑

显然(基于下面的注释),nodejs只有一个线程池在所有工作线程之间共享。如果是这样的话,那么获得每个磁盘一个单独池的唯一方法就是使用多个进程,而不是多个线程。

或者,您可以扩大工作池,然后创建自己的队列系统,一次只将每个单独磁盘的几个请求放入工作池,从而在不同的驱动器之间提供更多的并行性。

原始答案

(其中一些仍然适用)

如果没有工作线程,您将拥有一个为所有磁盘I/O请求提供服务的libuv线程池。因此,它们都将进入同一个池,一旦该池中的线程繁忙(无论它们为哪个磁盘提供服务),新的请求将按照它们到达的顺序排队。这可能不太理想,因为如果您有5个驱动器A请求、1个驱动器B请求和1个驱动器C请求,则您不希望仅先用5个驱动器B的请求填满池,因为这将使驱动器B和驱动器C的请求等待驱动器A上的多个请求完成后才能启动。这就失去了在单独的驱动器之间进行某种并行性的一些机会。当然,是否真正在单独的驱动器上实现并行还取决于驱动器控制器的实现,以及它们是否真的有单独的SATA控制器。

如果您确实使用了工作线程,每个磁盘一个nodejs工作线程,您至少可以保证在每个磁盘的线程池中都有一个单独的操作系统线程池,并且您可以使对一个驱动器的任何一组请求都不可能阻止对其他驱动器的请求启动,从而错过与对其他驱动器请求并行运行的机会。

当然,所有这些讨论都是理论性的。在磁盘驱动器、控制卡、控制器上的操作系统(在控制器上有libuv,在控制器上还有nodejs)的世界里,理论讨论有很多机会在现实世界的测量中不起作用。

因此,真正确定的唯一方法是实现工作线程选项,然后将其与具有几种不同磁盘使用场景的非工作线程选项进行基准比较,包括您认为可能是最坏情况的两种。因此,与任何与性能相关的重要问题一样,您将不可避免地必须以某种方式进行基准测试和衡量。而且,您的结果也需要非常仔细地构建基准测试,以便最大限度地发挥作用。

为了扩展每个进程模型,它看起来与jfriend00建议的工作线程相同,只是IPC机制发生了变化。

从"作业队列"管理作业队列;头部;管理器进程,并将驱动器/哈希工作拆分为每个工作进程的节点进程,这样每个工作进程中就不会出现IO/CPU争用。

让每个员工一次从其驱动器(或驱动器组)的工作队列中拿起一份工作。您所需要的只是可靠性、对未处理的工人的监控以及工人完成/错误的返回通道。

排队机制其实并不重要,一个数据库表就足够了(或者任何类型的网络消息传递http、grpc、nanomsg、redis、nats、rabbitmq.)。这是基于不需要在管理者和工人之间共享大量数据;嘿,工人,这里有一个文件去处理它"quot;我受够了这个文件";或";我破产了,救命">

| Manager                        |
| Pub 1 2 3                      |
| Sub 1    | Sub 2    | Sub 3    |
| Worker   | Worker   | Worker   |
|          |          |          |
| DriveA   | DriveC   | DriveE   |
| DriveB   | DriveD   | DriveF   |

如果进程最终被CPU限制,或者管理IO需求所需的数量较少,则为每个核心运行一个工作者。工作人员可以在添加驱动器或更多服务器时轻松扩展。

相关内容

最新更新