在Node.js中并行化任务

在JS中我有一些任务是资源密集型的。 对于这个问题,让我们假设他们是一些沉重的计算,而不是系统访问。 现在我想同时运行任务A,B和C,并在完成时执行一些函数D.

asynchronous库为此提供了一个很好的脚手架:

async.parallel([A, B, C], D); 

如果我正在做的只是计算,那么它仍然会同步运行(除非库将任务放在不同的线程本身,我认为不是这种情况)。 我如何使这实际上平行? 通常情况下,asynchronous代码不会阻塞调用者(使用NodeJS时)做什么? 它开始了一个孩子的过程 ?

我如何使这实际上平行?

首先,在单个节点应用程序中,您不会真正并行运行。 节点应用程序在单个线程上运行,并且一次只有一个事件由节点的事件循环处理。 即使在多核框中运行,也不会在节点应用程序中获得并行处理。

也就是说, 通过将代码分成单独的节点进程或产生subprocess ,可以在多核机器上获得处理并行性。 实际上,这允许您创build节点本身的多个实例,并以不同方式与这些进程进行通信(例如stdout,进程分叉IPC机制)。 此外,您可以select将function(通过责任)分离到自己的节点应用程序/服务器,并通过RPC调用它。

通常情况下, asynchronous代码不会阻塞调用者(使用NodeJS时)做什么? 它开始了一个孩子的过程?

这不是一个新的过程。 在下面, 当在node.js中使用async.parallel时 ,它使用process.nextTick() 。 nextTick()允许你避免阻塞调用者,把工作推迟到一个新的堆栈,这样你可以交错cpu密集型任务等。

长话短说

实现多处理器并发性的节点并不容易“开箱即用”。 节点,而不是给你一个非阻塞devise和一个事件循环,利用线程不共享内存。 多个线程不能共享数据/内存,因此不需要locking。 节点是无锁的 。 一个节点进程利用一个线程,这使得节点既安全又强大。

当你需要在多个进程中分割工作时,使用某种消息传递来与其他进程/服务器进行通信。 如IPC / RPC。


更多请参阅:

来自SO的真棒回答什么是Node.js …有很多善良的东西。

了解process.nextTick()

asynchronous和并行不是一回事。 asynchronous意味着你不必等待同步。 平行意味着你可以同时做多件事情。 Node.js只是asynchronous的,但它是唯一的一个线程。 一次只能做一件事。 如果你有一个长时间运行的计算,你应该启动另一个进程,然后让你的node.js进程asynchronous等待结果。

要做到这一点,你可以使用child_process.spawn,然后从标准input读取数据。

http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

 var spawn = require('child_process').spawn; var process2 = spawn('sh', ['./computationProgram', 'parameter'] ); process2.stderr.on('data', function (data) { //handle error input }); process2.stdout.on('data', function (data) { //handle data results }); 

请记住,I / O是由Node.js并行化的; 只有你的JavaScriptcallback是单线程的。

假设你正在编写一个服务器,添加产卵过程或分支的复杂性的另一种方法是简单地构build无状态的节点服务器,并为每个核心运行一个实例,或者更好的是在自己的虚拟化微服务器上运行多个实例。 使用反向代理或负载均衡器协调传入的请求。

您也可以将计算卸载到另一台服务器,也许MongoDB(使用MapReduce)或Hadoop。

要成为真正的核心,你可以用C ++编写一个Node插件,并且对并行化的计算代码进行细粒度的控制。 无论如何,从C ++加速可能会否定并行化的需要。

您总是可以编写代码来执行最适合数值计算的另一种语言的计算密集型任务,例如通过REST API公开它们。

最后,你也许可以使用node-cuda或类似的计算方法在GPU上运行代码(不是所有的GPU都可以优化)。

是的,你可以分叉和产生其他进程,但是在我看来,节点的主要优点之一是不必太担心并行化和线程化,因此绕过了大量的复杂性。

刚刚遇到的parallel.js,但它似乎实际上是使用多核心,也有地图缩减types的function。 http://adambom.github.io/parallel.js/

根据你的用例,你可以使用类似的东西

task.js简化了CPU密集代码在所有内核上运行的接口(node.js和web)

一个例子是

 function blocking (exampleArgument) { // block thread } // turn blocking pure function into a worker task const blockingAsync = task.wrap(blocking); // run task on a autoscaling worker pool blockingAsync('exampleArgumentValue').then(result => { // do something with result });