nodejs是单进程单线程的,影响事件驱动服务模型性能的点在于CPU的计算能力,它的上限决定这类服务模型的性能上限,但不受多进程或多线程模式中资源上限的影响。可解决多核CPU利用问题。
多进程架构:Node提供child_process模块,并提供child_process.fork()函数提供我们实现进程复制
1.复制主进程,根据cpu核数复制工作进程。它需要至少30毫秒的启动时间和至少10MB的内存。
在Master-Worker模式中可通过onmessage()和postMessage()进行通讯
//parent.js var cp=require('child_process'); var n=cp.fork(__dirname+'/sub.js'); n.on('message',function(m){ console.log('PARENT got message:',m); }); n.send({hello:'world'}); //sub.js process.on('message',function(m){ console.log('CHilD got message:',m); }); process.send({foo:'bar'});
2.创建子进程
child_process模块给予Node可以随意创建紫禁城的能力。四个方法
spawn():启动一个子进程来执行命令。
exec():启动一个子进程来执行命令,与spawn()不同的是接口不同,提供一个回掉函数获知子进程的状况
execFile():启动一个字进程来执行可执行文件。执行文件首行内容必须添加: #!/usr/bin/env node
fork():与spawn()类似,不同的是只需要指定要执行的JavaScript文件模块即可
句柄传递:
句柄是一种可以用来标识资源的引用,它的内部包含了对象的文件描述符。可以用来标识一个服务器端的socket对象,一个客户端socket对象,一个UDP套接字一个管道等。
可以把TCP服务器发送给子进程。
可发送的句柄类型包括:
net.Socket TCP套接字
net.Server TCP服务器,任意建立在TCP服务商的应用层服务都可以使用
net.Native C++层面的TCP套接字或IPC管道
dgram.Socket UDP套接字
dgram.Native C++层面的UDP套接字
//parent.js var cp=require('child_process'); var child1=cp.fork('child.js'); var child2=cp.fork('child.js'); var server=require('net').createServer(); server.on('connection',function(socket){ socket.end('主线程进行处理\n'); }); server.listen(1337,function(){ child1.send('server',server); child2.send('server',server); }); //child.js process.on('message',function(m,server){ if(m==='server'){ server.on('connection',function(socket){ socket.end('子线程进行处理\n'); }) } });结果可能被父进程处理,也可能被子进程处理,并且是在tcp层面完成事情,我们可以将转化为HTTP层面
//parent.js var cp=require('child_process'); var child1=cp.fork('child.js'); var child2=cp.fork('child.js'); var server=require('net').createServer(); server.listen(1337,function(){ child1.send('server',server); child2.send('server',server); //主进程服务关掉 server.close(); }); //child.js var http=require('http'); var server=http.createServer(function(req,res){ res.writeHead(200,{'Content-Type':'text/plain'}); res.end('子进程HTTP处理:pid is '+process.pid+'\n'); }) process.on('message',function(m,tcp){ if(m==='server'){ tcp.on('connection',function(socket){ server.emit('connection',socket); }) } });以上代码可实现,多个子进程同时监听同一个端口,且主进程不监听