我们知道nodejs是单线程的,若在一个线程中运行一个响应很长时间nodejs程序,那么其他的请求要等这个程序完成后在去执行,这样cpu利用率很低,若为每个请求单独一个进程处理,这样可以利用好服务器的资源。nodejs为我们提供了child_process与cluster模块为我们提供多进程的操作。其中child_process开启多个子进程,在各个子进程中运行nodejs命令,可执行文件、nodejs模块文件。cluster运行多个子进程,在每个子进程中运行nodejs应用程序的副本。
nodejs中的进程
在nodejs中,使用process对象代表nodejs程序
进程对象process拥有的属性
execPath 运行可执行文件的绝对路径
version nodejs版本号
versions nodejs及nodejs运行所依赖的版本号
platform 运行nodejs的平台
stdin 标准输入对象,默认情况,该输入流对象处于暂停状态,必须使用process.stdin.resume()恢复读取标准输入流数据
stdout 标准输出流对象
stderr 错误输出流对象,这两写入输出流对象与其他的写入输出流对象不同之处在于,这两个是阻塞式操作,只有其他的读取输入流的pipe方法,并且参数为这个写入输出流时候,才为非阻塞式操作
args 运行nodejs程序所有参数的数组 如node app.js one two args数组中[node,app.js one two]
env 运行nodejs环境信息
pid 运行nodejs应用程序的pid
我们看一个stdin stdout例子
process.stdin.resume();
process.stdin.on('data',function(data){
process.stdout.write('jinchengjieshoushuju'+data);
})
运行结果
process.argv
process.argv.forEach(function(val,index){
console.log(index+":"+val);
})
执行结果如下
nodejs应用程序process所具有的方法
memoryUsage()内存使用量
rss:表示nodejs内存消耗量
heapTotal:表示v8所分配的内存量
heapUsed:表示v8内存消耗量
nextTick推迟函数的执行到下一个同步方法执行完成或异步方法事件回调函数开始执行
process.nextTick() setTimeout(也可以推迟,前者速度快
var fs=require("fs");
function foo(){
console.log("文件执行完毕");
}
process.nextTick(foo);
console.log(fs.readFileSync('./text.txt','utf-8'));
让读取完文件text.txt之后,执行foo函数
执行结果
chdir
修改当前工作目录
cwd:获取当前工作目录
console.log('old'+process.cwd())
process.chdir('../27')
console.log('now'+process.cwd())
exit([code])
退出process,0正常退1非正常
当调用exit方法时候触发exitshijian
process.on('exit',function(){
console.log("jinchengtuichu")
})
process.exit()
uptime()获取当前nodejs程序运行了多长时间
hrtime()表示代码运行了多长时间
var time=process.hrtime();
var diff=process.hrtime(time)
使用spawn方法创建子进程,运行nodejs命令
child_process.spawn(commond,[args],[options])
开启一个进程执行命令,commond是要执行的命令,args是执行命令所带的参数,optians是开启中这个进程的一些信息项
cwd:指定子进程当前工作目录
sdtio:字符串或者3个属性的数组,表示标准输入输出流信息,可选信息为
pipe:子进程与父进程通过通道连接,在父进程中,childProcess.stdio[0]表示标准输入流对象,childProcess.stdio[1]表示标准输出流对象,childProcess.stdio[2]表示标准错误输出流对象,
ipc:表示子进程与父进程之间开启一个ipc通道用于传输消息,或文件描述符,一个子进程只能有一个ipc通道,设置该选项使子进程的send方法被使用,send发送消息了会触发message事件
stream:表示子进程 与父进程共享一个设备文件端口,数据底层文件描述符将在子进程中被复制。
ignore ,忽略,不为子进程设置标准输入输出错误输出文件描述符,默认时候是使用0文件描述符用于标准输入1文件描述符标准输出。2错误输出,忽略了nodejs吧子进程的文件描述符定义到dev/null(空设备文件)
null或undefined对于标注输入输出使用管道,错误使用ignore
字符串形式的标准输入输出错误输出
如‘pipe’---》【pipe.pipe,pipe】
ignore-->[ignore,ignore,ignore]
inherit-->[process.stdin,process.stdout,process.stderr]或者【0.1.2】
env :环境信息,不指定为空
detached:是不是领头进程,若为true,表示父进程结束了,这个进程还可以继续使用
child_process.spawn(commd,[],{stdio:'inherti'})返回一个childprocess对象,与进程一样,都有process的属性方法
子进程中的时间 close与exit
当子进程中所有的输入输出都关闭,并且进程退出触发close事件,当进程退出,输入输出没有关闭(一个进程可能有多个子进程,各个子进程共享stdio)触发exit事件
child.on('close',function(code,signal){})
child.on('exit',function(code,signal){})
主进程代码
var child_process=require("child_process");
var p1=child_process.spawn('node',['test1.js','one','ww','rr']);
var p2=child_process.spawn('node',['text2.js'],{stdio:'pipe'});
p1.stdout.on('data',function(data){
console.log("子进程标准输出"+data)
p2.stdin.write(data);
//在父进程中关闭杀掉子进程,触发子进程的exit事件,code为不正常退出
p1.kill();
})
p1.on('exit',function(code,signal){
if(code){
console.log("子进程退出,退出代码"+code)
process.exit();
}else{
console.log("子进程退出,退出信号"+signal)
}
})
p1.on("error",function(err){
console.log(err);
process.exit();
})
//子进程关闭,与退出exit区别是,退出子进程,子进程用的流什么的还可能存在,比如多个子进程与父进程共享一个输出输入流,这个子进程关闭了,别的子进程没有关闭。
p1.on('close',function(code,signal){
console.log('子进程关闭');
process.exit();
})
test1.js
//process.stdin是读取数据流、process.stdout/stderr是标准输出流对象childstdin是输出刘对象,
process.stdout.write("子进程工作目录"+process.cwd());
process.argv.forEach(function(index,val,array){
process.stdout.write("\r\n"+index+":"+val);
})
text2.js
var fs=require("fs");
var out=fs.createWriteStream('./song.txt');
process.stdin.on('data',function(data){
out.write(data);
})
process.stdin.on('end',function(data){
process.exit();
})
执行效果
var child_process=require("child_process");
var p1=child_process.spawn('node',['test1.js','one','ww','rr'],{stdio:['ipc','pipe','ignore']});
var p2=child_process.spawn('node',['text2.js'],{stdio:'pipe'});
p1.stdout.on('data',function(data){
console.log("子进程标准输出"+data)
p2.stdin.write(data);
p1.kill('SIGTERM');
})
p1.on('exit',function(code,signal){
if(code){
console.log("子进程退出,退出代码"+code)
process.exit();
}else{
console.log("子进程退出,退出信号"+signal)
}
})
p1.on("error",function(err){
console.log(err);
process.exit();
})
p1.on('close',function(code,signal){
console.log('子进程关闭');
process.exit();
})
//当子进程与父进程开启ipc通道通信时候,通道关闭触发这个事件
p1.on('disconnect',function(){
console.log('通道关闭')
})
正常情况下,子进程都结束父进程才退出,为了让父进程提前结束,子进程继续执行任务,我们提供了一个detached=true,并且使用子进程对象的unref方法允许父进程退出,若子进程与父进程共享输出流的,那么不允许父进程提前退出
主进程代码(主进程与子进程是通过文件描述符fd来通信的,一个整数)
var child_process=require("child_process");
var fs=require('fs');
var out=fs.openSync('./song.txt','a');
var p1=child_process.spawn('node',['write.js'],{detached:true,stdio:['ignore',out,'ignore']});
p1.unref();
子进程
for(var i=0;i<10000;i++){
process.stdout.write(i.toString());
}
运行结果