2013-10-15 46 views
0

我有一个基本上缓存来自Web服务的数据的Node.js应用程序。 我也有一个队列可以接收大约500件需要尽快处理的物品。通过处理,我的意思是它们中的每一个代表一个HTTP请求,并且它的响应被缓存。在Node.js中模拟线程

现在,Node的单线程体系结构并不适合这种情况。理想情况下,我想产生5-10个“线程”以尽快处理队列。我读了一个child_process模块,可以分叉进程,但我从来没有使用它。该模块可以帮助吗?

任何人都可以提出这个问题的解决方案吗?

+3

节点中的任何异步IO都是使用后台线程创建的。另外,Node可以处理比Apache更大的数据量,例如,所以只有当你达到一个荒谬的请求数时,你应该考虑分叉进程:) – gustavohenke

+2

我同意+ gustavohenke。大多数情况下,只需使用setTimeout和setInterval就可以防止阻塞。如果您因任何原因必须创建子进程,请查看以下内容:http://nodejs.org/api/child_process.html。此外,最新的node.js版本针对在相同端口上侦听的一组node.js进程有一个beta版实现,更多信息请看这里:http://nodejs.org/api/cluster.html – StMotorSpark

+0

嗨,大家好。这里的问题不是并发性。这是关于处理速度。我已经使用setTimeout。问题是我需要尽可能快地处理物品。这就是为什么我正在研究“线程”。例如,如果我有5个线程处理队列,它将以比我现在拥有的更快的速度完成 – Thomas

回答

2

child_processes简单地说是分支运行相同或不同脚本的新节点进程。 你可以使用该API来产生系统进程,但这不是我将在这里描述的。

它们表现得像真正的nodejs进程,因为那就是它们。

有一个很大很大的消极的一面:

你需要记住,产卵一个节点过程花费了大量的时间和ressources所以usualy其更快地计算一个节点的过程中数据或产卵工人童车到沟通工作。正如你在文档中看到的那样,你可以发送和接收来自和进入child_process的数据,这使得你可以将工作委托给已经产生的孩子。

子进程通常与生成它的进程共享相同的stdin和stdout,除非您更改它。只要看看文档。它非常有据可查,并且易于使用。

child_process documentation

我从来没有取得工人的孩子的,但这样至极,你可以考虑有用我所做的东西。

if (process.argv.indexOf("child") == -1) { 
    process.chdir(module.filename.replace(/\/[^\/]+$/, "")); 
    var child; 
    var spawn = function() { 
    console.log("spawning child process " + new Date()); 
    child = require("child_process").fork(module.filename, ["child"]); 
    child.on("close", function() { 
     spawn(); 
    }); 
    } 
    spawn(); 

    process.on("exit", function() { 
    child.kill(); 
    }); 
    return; 
} 

// child code begins here 

var fs = require("fs"); 

fs.watch(process.argv[1], function() { 
    process.exit(); 
}); 
0

child_process模块​​将有所作为你想要的。

唯一的问题是,你从字面上产生新的进程,因此,有一个内存开销,你必须考虑。假设您想要在同一文件中定义子例程的优雅,您可以将JavaScript字符串传递给node命令。

所以这正是我们要做的。但首先,让我们来创建一个接受JSON兼容对象的功能,和功能,然后将上一个新的线程运行函数:

var child_process = require('child_process'); 

function startThread(data, fn, callback) { 
    var fnStr = '(' + fn.toString() + ')(' + JSON.stringify(data) + ');'; 

    var node = child_process.spawn('node', ['-e', fnStr]); 

    var output = []; 

    var onData = function (data) { 
    output.push(data.toString('utf8').trim()); 
    }; 

    node.stdout.on('data', onData); 
    node.stderr.on('data', onData); 

    node.on('close', function (code) { 
    callback(code, output); 
    }); 
} 

而作为一个例子,我们将要产生一个新的线程产生了“99瓶啤酒”歌曲的歌词:

startThread({ doFor: '99' }, function (data) { 
    var str = ''; 
    while (data.doFor) { 
    str += data.doFor + ' bottles of beer on the wall ' + data.doFor + 
    ' bottles of beer. You take one out, toss it around, '; 
    data.doFor--; 
    str += data.doFor + ' bottles of beer on the wall\n'; 
    } 
    console.log(str.trim()); 
}, function (code, outputs) { 
    console.log(outputs.join('')); 
}); 

不幸的是,将在其他的“线程”所使用的函数将不能访问变量父线程。

而且,数据通过STDOUT和STDERR传递。