6

有代码,

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.)

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

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

我运行代码的机器只有 1GB 的 RAM Ubuntu,所以我让应用程序挂在那里一次,会不会是资源不足造成的?

4

4 回答 4

5

您的直觉是正确的,并行性不是免费的,但您当然可以为此付费。

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

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

除此之外,使用 async.parallel 的常见缺陷包括想要比该函数提供的更复杂的控制流(根据您的描述,这似乎并不适用)以及天真地在太大的集合上使用并行(比如说,这可能会导致您如果您正在编写许多文件,则会遇到系统的文件描述符限制)。对于 1GB RAM 上的约 200 次请求和保存操作,我想只要您不在事件处理程序中进行太多按摩,您就可以了,但如果您遇到服务器挂起,parallelLimit 可能是一个很好的出路。

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

于 2013-08-05T21:38:03.790 回答
3

我要指出的是并发async.parallel执行多个函数而不是(完全)并行。它更像是虚拟并行。

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

node 最好的一点是你不必担心 I/O。它非常有效地处理 I/O。

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


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

当负担过重时,您也可能会遇到套接字错误ECONNRESET(错误:套接字挂起),ECONNREFUSEDETIMEDOUT. 所以妥善处理它们。还要检查 mongoDB 服务器的最大同时连接数。


最后,服务器可以因为垃圾收集而挂断。垃圾收集在您的内存增加到某个点后开始,然后在一段时间后定期运行。V8 可以拥有的最大堆内存约为 1.5 GB,因此如果其内存很高,预计 GC 会频繁运行。process out of memory如果要求超过该限制,节点将崩溃。所以修复程序中的内存泄漏。你可以看看这些工具

于 2013-08-07T06:34:28.957 回答
0

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

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

于 2013-08-03T11:26:03.300 回答
0

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

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

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

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

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

这是原子性的对立面(所以也许要注意特殊数据库操作的原子性 - 但那是另一个话题)

所以也许使用起来更快:

T2.U1 before T1.U1 

- 这没问题,直到

T2.U1 is based on T1.U1

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

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

于 2013-08-09T01:39:45.360 回答