node的一个最大特性就是单线程,单线程带来的好处是不用像多线程编程那样去考虑状态的同步问题,也不用去担心出现死锁,也没有线程上下文所带来的性能的开销。
同时也带来了一些问题,比如无法充分利用的多核CPU,线程会阻塞的问题。
- process对象。
- child_process对象。
- cluster模块。
process 对象
process模块允许你获得或者修改当前node进程的设置,不想其他的模块,process是一个全局进程(node主进程),你可以直接通过process变量直接访问它。
在nodejs使用中,有一种情况比如:函数不存在、语法错误什么的,整个nodejs运行断掉,程序停止。
process模块提供了uncaughtException 事件用于处理这个问题。
process.on('uncaughtException', function (err) { console.log('Caught exception: ' + err);});setTimeout(function () { console.log('This will still run.');}, 500);// Intentionally cause an exception, but don't catch it.nonexistentFunc();console.log('This will not run.');复制代码
process 属性
process.version://包含当前node实例的版本号;process.platform://列举node运行的操作系统的环境,只会显示内核相关的信息,如:linux2, darwin,而不是“Redhat ES3” ,“Windows 7”,“OSX 10.7”等;process.uptime()://包含当前进程运行的时长(秒);process.getgid(), process.setgid()://获取或者设置group id;process.getuid(), process.setuid()://获取或者设计user id;process.pid://获取进程id;process.title://设置进程名称;process.execPath://当前node进程的执行路径,如:/usr/local/bin/node;process.cwd()://当前工作目录;process.memoryUsage()://node进程内存的使用情况,rss代表ram的使用情况,vsize代表总内存的使用大小,包括ram和swap;process.heapTotal,process.heapUsed://分别代表v8引擎内存分配和正在使用的大小。process.env 查看环境变量复制代码
process.stdin.resume(); //这句话是为了不让控制台推出 process.on('SIGINT', function () { //SIGINT这个信号是系统默认信号,代表信号中断,就是ctrl+c});复制代码
自定义监听process事件on
process.on('SIGUSR1', function (d) { //这里监听 SIGUSR1 事件 console.log('Bye-'+d); //这里将输出Bye-Bye,然后推出进程 process.exit(0); }); process.emit('SIGUSR1', 'Bye'); //利用emit触发SIGUSR1,然后传参数为Bye复制代码
console.log = function (d) { process.stdout.write(d + '\n');};复制代码
process.stdin.resume();process.stdin.setEncoding('utf8');process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk);});process.stdin.on('end', function () { process.stdout.write('end');});复制代码
child_process属性
- 可以实现创建多进程,以利用单机的多核计算资源。
- 可以在程序中直接创建子进程,并使用主进程和子进程之间实现通信,等到子进程运行结束以后,主进程再用回调函数读取子进程的运行结果。
- child_process.exec()
- child_process.spawn()
process.exec 执行系统命令
var cp = require('child_process');cp.exec('ls -l', function(e, stdout, stderr) { if(!e) { console.log(stdout); console.log(stderr); }});复制代码
自定义 options
var options = { encoding: 'utf8', // I/O流的编码格式; timeout: 0, // 进程超时时间; maxBuffer: 200 * 1024, // 当时间或者缓冲区超限时终止进程的信号; killSignal: 'SIGTERM', // stdout或stderr可增长的最大值; setsid: false, // 决定在进程中是否创建一个新的会话; cwd: null, // 进程的初始工作目录,为null时表示使用node的当前工作目录; env: null // 进程的环境变量。};var cp = require('child_process');cp.exec('ls -l', options, function(e, stdout, stderr) { if(!e) { console.log(stdout); console.log(stderr); }});复制代码
process.spawn
var cp = require('child_process');var cat = cp.spawn('cat');cat.stdout.on('data', function(d) { console.log(d.toString());});cat.on('exit', function() { console.log('kthxbai');});cat.stdin.write('hello world!');cat.stdin.end();***child_process.spawn( )比child_process.exec( )更加强大和灵活复制代码
cluster
cluster模块可以轻松实现运行在同一机器不同进程上的TCP或HTTP服务器集群。它们仍使用相同的底层套接字,从而在相同的IP地址和端口组合上处理请求。
fork: //当新的工作进程已经被派生时发出。callback函数接收worker对象作为唯一的参数。function(Worker)online: //当新的进程发回一消息,表明它已经启动时发出。callback同上。listening: //当工作进程调用listen()开始监听端口时发出。callback:fucntion(Worker,address)disconnect: //当IPC通道被切断时发出。如服务器调用worker.disconnect()的时候。callback:function(Worker)exit: //在Worker对象已断开时发出。callback:function(Worker,code,signal)setup: //在setupMaster()被首次调用时发出。属性和方法:settings: //包含exec(工作进程的javascript文件)、args(传递的参数数组)、silent(断开工作进程的IPC机制)属性值,用于建立集群isMaster: //判断当前进程是否是主进程isWorker: //判断当前进程是否是工作进程setupMaster([settings]): //启动主进程disconnect([callback]): //断开工作进程的IPC机制,并关闭句柄,当断开连接完成时回调worker: //引用在工作进程的当前Worker对象workers://包含Worker对象,可以通过标识从主进程引用它们。cluster.workers[workerId]复制代码
var cluster = require('cluster');var http = require('http');if (cluster.isMaster) { cluster.on('fork', function(worker) { console.log("Worker " + worker.id + " created"); }); cluster.on('listening', function(worker, address) { console.log("Worker " + worker.id +" is listening on " + address.address + ":" + address.port); }); cluster.on('exit', function(worker, code, signal) { console.log("Worker " + worker.id +" Exited"); }); cluster.setupMaster({ exec:'cluster_worker.js'}); //图例二js demo var numCPUs = require('os').cpus().length; for (var i = 0; i < numCPUs; i++) { if (i>=4) break; cluster.fork(); } Object.keys(cluster.workers).forEach(function(id) { cluster.workers[id].on('message', function(message){ console.log(message); }); });}复制代码
const cluster = require('cluster');const http = require('http');const numCPUs = require('os').cpus().length;if (cluster.isMaster) { console.log(`主进程 ${process.pid} 正在运行`); // 衍生工作进程。 for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`工作进程 ${worker.process.pid} 已退出`); });} else { // 工作进程可以共享任何 TCP 连接。 // 在本例子中,共享的是一个 HTTP 服务器。 http.createServer((req, res) => { res.writeHead(200); res.end('hellow world \n'); }).listen(8000); console.log(`工作进程 ${process.pid} 已启动`);}复制代码
var cluster = require('cluster');var http = require('http');if (cluster.isWorker) { http.Server(function(req, res) { res.writeHead(200); res.end("Process " + process.pid + " says hello"); process.send("Process " + process.pid + " handled request"); }).listen(8080, function(){ console.log("Child Server Running on Process: " + process.pid); });}复制代码