Node.js异步并行 - 后果是什么?

时间:2013-08-03 11:13:02

标签: node.js sockets ubuntu asynchronous

有代码,

async.series(tasks, function (err) {
    return callback ({message: 'tasks execution error', error: err});
});

其中,tasks是函数数组,每个函数都执行HTTP请求(使用request模块)并调用MongoDB API来存储数据(到MongoHQ实例)。

使用我当前的输入(~200要执行的任务),需要

  [normal mode] collection cycle: 1356.843 sec. (22.61405 mins.)

但只是尝试从series更改为parallel,它会带来巨大的好处。几乎相同数量的任务在~30 secs而不是~23 mins中运行。

但是,知道没有任何东西是免费的,我试图了解这种变化的后果是什么?我可以说开放套接字的数量会更高,内存消耗更多,对数据库服务器的影响更大吗?

我运行代码的机器只有1GB的RAM Ubuntu,所以我这样应用程序挂起一次,是否可能是由于资源不足造成的?

4 个答案:

答案 0 :(得分:5)

你的直觉是正确的,并行性不是免费的,但你当然也许能够付出代价。

使用负载测试模块(或模块集合),如nodeload,您可以量化此并行操作如何影响您的服务器,以确定它是否可接受。

如果需要,

Async.parallelLimit可以是限制服务器负载的好方法,但首先,发现是否需要限制非常重要。显式测试是发现系统限制的最佳方式(eachLimit具有不同的签名,但也可以使用)。

除此之外,使用async.parallel的常见缺陷包括需要比函数提供的更复杂的控制流(从您的描述看起来似乎不适用),并且天真地在太大的集合上使用并行(例如,如果您正在编写许多文件,可能会导致您进入系统的文件描述符限制)。在1GB RAM上进行~200请求和保存操作时,我认为只要你没有在事件处理程序中进行太多按摩,你就会没事,但如果你遇到服务器挂起,parallelLimit可能是一个很好的出路。

同样,测试是解决这些问题的最佳方式。

答案 1 :(得分:3)

我想指出async.parallel执行多个功能并发而不是(完全)并行。它更像是虚拟并行。

并发执行就像通过多任务/调度在单个CPU核心上运行不同的程序一样。真正的并行执行将在多核CPU的每个核心上运行不同的程序。这很重要,因为node.js具有单线程体系结构。

关于节点的最好的事情是你不必担心I / O.它非常有效地处理I / O.

在您的情况下,您将数据存储到MongoDB,主要是I / O.因此,并行运行它们将耗尽您的网络带宽,如果从磁盘读取/写入,则磁盘带宽也是如此。由于CPU过载,您的服务器不会挂起。


这样做的结果是,如果您的服务器负担过重,您的请求可能会失败。您可能会收到EMFILE错误(打开的文件太多)。每个套接字都算作一个文件。通常连接是池,意味着建立连接从池中拾取套接字并在完成返回池时。您可以使用ulimit -n xxxx增加文件描述符。

ECONNRESET(错误:套接字挂断),ECONNREFUSEDETIMEDOUT等负担过重,您也可能会收到套接字错误。所以正确处理它们。另请检查mongoDB服务器的最大并发连接数。


最后,由于垃圾回收,服务器可能会挂起。垃圾收集在您的内存增加到某一点后启动,然后在一段时间后定期运行。最大堆内存V8可以具有大约1.5 GB,因此如果GC的内存很高,则期望GC频繁运行。如果要求更多,那么节点将与process out of memory一起崩溃。因此,修复程序中的内存泄漏。您可以查看这些tools

答案 2 :(得分:0)

您将看到的主要缺点是数据库服务器负载飙升。根据您的设置,这可能会也可能不会。

如果您的数据库服务器是共享资源,那么您可能希望使用async.eachLimit来限制并行请求。

答案 3 :(得分:0)

如果多个用户连接,您将意识到差异:

在这种情况下,处理器可以处理多个操作

asynch尝试运行多个用户相对相等的多个操作

T = task
U = user
(T1.U1 = task 1 of user 1)

T1.U1 => T1.U2 => T2.U1 => T8.U3 => T2.U2 => etc

这是atomicy的对话(所以也许在特殊的db操作上注意atomicy - 但那是另一个话题)

所以也许使用起来更快:

T2.U1 before T1.U1 

- 直到

才会有问题
T2.U1 is based on T1.U1

- 这可以通过使用回调/或因此回调来防止

...希望这是你想知道的......这有点晚了