总所周知,Node.js 中的异步 I/O 编程特点,非常适合处理 I/O 密集型的情况,但是由于 javascript 单线程的特点,使 Node.js 对于处理 CPU 密集型问题却成为了 Node.js 的弱项,如果遇到 CPU 密集型问题,我们该怎么处理呢,下面我总结了几个相关处理方法:
创建子进程:
Node.js 的 child_process 模块提供了创建工作子进程的方式来弥补单线程的缺点,使其尽量不要堵塞整个线程的运行,一共提供了如下四个函数:
- spawn:执行简单命令,不支持 callback 函数。
var child = require('child_process');
var du = child.spawn('du', ['-sh', '/disk1']);
du.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
du.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
du.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
- exec:exec函数是对spawn的一种友好封装,增加Shell命令解析,可以直接嵌入复杂的命令,支持callback函数。
var childProcess = require('child_process');
var ls = childProcess.exec('cat *.js | wc', function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
}
console.log('Child Process STDOUT: '+stdout);
});
- execFile:execFile函数会直接执行特定的程序,参数作为数组传入,不会被bash解释,因此具有较高的安全性。execFile与spawn的参数相似,也需要分别指定执行的命令和参数,但可以接受一个回调函数,与exec的回调函数相同。
var childProcess = require('child_process');
var path = ".";
childProcess.execFile('/bin/ls', ['-l', path], function (err, result) {
console.log(result)
});
- fork:fork 衍生一个新的 Node.js进程,会在父进程与子进程之间建立一个IPC通信管道。每个进程都有自己的内存,使用自己的 V8 实例。 由于需要额外的资源分配,因此不推荐衍生大量的 Node.js 进程。
let fork = require('child_process').fork;
let path = require('path');
module.exports = function (content, filePath) {
return new Promise(function (res, rej) {
let task = fork(path.resolve(__dirname, 'exportExcel.js'));
task.send({
content: content,
filePath: filePath
});
task.on('close', res);
task.on('error', rej);
});
};
process.on('message', function (opt) {
let XLSX = require('xlsx');
/*****
excel表格生成计算过程....
******/
XLSX.writeFile(wb, opt.filePath);
process.exit(0);
});
console.log(ctx.query);
console.log(ctx.request.query);
ctx.body = {a: 1};
ctx.response.body = {a: 1};
鉴于频繁的创建子进程和关闭子进程,资源消耗比较大,不建议在代码里大量使用子进程的方式去实现。对于部分 CPU 消耗比较大函数,可以在子进程里实现,不要堵塞主进程的正常执行。
部署多个实例
同一台机器上部署多个实例,利用负载均衡管理工具来实现请求的均匀分发,这样每个实例使用一个 CPU,能提高多核 CPU 的利用率,常见的 Node.js 多实例管理工具如下:
抽取子服务模块
如果确定有些功能 CPU 消耗特别高,且功能比较独立,我们完全可以将其独立出来,实现一个子服务,通过 rpc 方式调用。减少主服务的压力

2007

被折叠的 条评论
为什么被折叠?



