Nodejs学习之多进程架构
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs学习之多进程架构相关的知识,希望对你有一定的参考价值。
操作系统的资源是有限的,这通常意味者操作系统分配给进程或线程的资源是有限的,在多核cpu普及的时代,如果只使用单核(常说node是单线程的),则无法充分压榨硬件性能,今天和大家介绍的就是nodejs多进程架构,希望可以帮助大家更好的学习nodejs ,一起来看看吧。模块介绍
node提供了child_process模块,该模块提供4个方法
1.spawn() 启动一子进程来执行命令
2.exec() 启动一子进程来执行命令,与spawn()不同的是提供一个回调函数获知子进程的状况
3.execFile() 启动一个子进程来执行可执行文件
4.fork() 与spawn()类似,指定执行的javascript文件模块即可
惯用做法
通常,node项目会有个bin目录,里面的文件类似于应用程序入口,结合 commander 包实现根据命令行参数执行相应代码逻辑的功能:
var child_process = require(’child_process’); var fs = require(’fs’); var os = require(’os’); var program = require(’commander’);
const EventEmitter = require(’events’).EventEmitter; const ee = new EventEmitter();
var config = require(’../config.json’); var DEFAULT_TRG_PATH = config.triggersPath;
program.command(’start’)
.description(’start the application’)
.option(’-d, --directory,’, ’triggers path’, DEFAULT_TRG_PATH)
.action(function(opts) {
start(opts);
});
program.command(’create’)
.description(’start create’)
.option(’-d, --directory,’, ’triggers path’, DEFAULT_TRG_PATH)
.action(function(opts) {
create(opts);
});
program.parse(process.argv);
function start(opts){
console.log(1111);
}function create(opts){
console.log(1111);
}
假设需要执行 start 方式,仅需在命令行带上 start参数即可:
node ./bin/www start
同理,其他方法可以通过该方式按需调用. 都不到为啥会扯到commander包的使用,可能是通常情况下想使用多进程架构时功能已经足够复杂,而首先想到的就是用commander包使程序看上去比较好看吧-_-
好了,言归正传,其实我就想使用线程池这种所谓的高级语言封装好的方法而已,可惜node并没有这种.
很多文章都说过,API的用法,这里只简单说说他们之间的区别.
spawn
spawn会返回一个代后stdout与stderr流的对象,可以通过stdout流来读取子进程返回给主进程的数据.如果子进程需要返回大量数据,则应该使用spawn而不是exec. 注意,stdout是以buffer格式返回,相对于exec而言,buffer数据可以很大,也就是说如果主进程需要接收子进程大量的数据时,应该选择spawn来实现:
var absScript = path.resolve(process.cwd()+’/lib/’, ’child.js’); var child = child_process.spawn(process.argv[0],[absScript,’create’,’--path=’ + dConfig.triggersPath + trgFile]);
child.stdout.on(’data’, function(data){
console.log(`${data}`);
});
child.stdout.on(’end’, function(){
console.log(’end’);
});
child.on(’error’, function(err){
console.log(’Failed to start child process.’);
});
child.on(’close’,function(code){
console.log(’closecode:’+ code);
});
//child.jsconsole.log(’modelhunter.js’); var fs = require(’fs’); var program = require(’commander’); var trgs = require(’./components/trgs’); var ModelHunter = module.exports = {};
program.command(’create’)
.description(’create’)
.option(’-p, --path,’, ’triggers path’, ’’)
.action(function(opts) {
if(opts.path.length>0){
console.log(opts.path);
setTimeout(function(){
console.log(’aaaaaaa’);
process.exit(0);
},1000);
}
});
program.parse(process.argv);
最终输出为
modelhunter.js D:/xxxxx.xx
aaaaaaa
end closecode:0
exec 与 execFile
exec相当于spawn,通讯的内容有限制.适合执行复杂的shell命,与主进程的通讯是一次性的,子进程的结果只能返回一次.
execFile跟exec类型,执行一个文件,或脚本或可执行文件等
exec做了相当的封装,主要用于执行复杂的shell命令.
fork
fork使用同样的进程复制自身的环境执行脚本,但只能执行node脚本,fork可以很方便的与主进程进行通讯:
//注意这里第一个参数即是目标脚本的路径.var absScript = path.resolve(process.cwd()+’/lib/’, ’modelhunter.js’); var child = child_process.fork(absScript,[’create’,’--path=’ + dConfig.triggersPath + trgFile]);
child.on(’message’,function(m){
console.log(’message:’+ m); //接收子进程消息
});
child.on(’close’,function(code){
console.log(code);
});
child.send(’null’); //向子进程发送消息
//child.js
process.on(’message’,function(m){
console.log(’chilid Listen:’, m); //接收主进程消息
});
process.send(’this childprocess’); //向主进程发送消息
总结
如果想使用多进程架构,按需选择相应的API.即可实现类似"进程池"的功能,当然,可能要配合事件通知机制.
这里提出几点疑问:
1.如果是一个网站的服务端,为了充分利用CPU资源,通常会使用多进程架构,但是我们应该选择fork还是spawn呢?
2.pm2的fork mode 与 cluster mode有什么区别?
文章来源:繁星UED
以上是关于Nodejs学习之多进程架构的主要内容,如果未能解决你的问题,请参考以下文章